2012-02-05 27 views
17

एक कार्यान्वयन के लिए जो f0 और f1 को उसी बाइट में पैक करता है, नीचे दिया गया प्रोग्राम परिभाषित किया गया है?बिट-फ़ील्ड और अनुक्रम बिंदु

struct S0 { 
     unsigned f0:4; 
     signed f1:4; 
} l_62; 

int main (void) { 
     (l_62.f0 = 0) + (l_62.f1 = 0); 
     return 0; 
} 

मुझे सी 99 और सी 11 के जवाब में दिलचस्पी है यदि ऐसा लगता है कि यह अलग है। 2:

पिछले और अगले अनुक्रम बिंदु एक वस्तु एक अभिव्यक्ति के मूल्यांकन से अधिकतम एक बार अपने संग्रहीत मूल्य मोदी फाई एड होगा बीच

C99 में, मैंने पाया 6.5 था। [...]

यह मेरे लिए स्पष्ट नहीं है कि इस पैराग्राफ के ऊपर के कार्यक्रम पर क्या परिणाम हैं।

बड़ी संख्या में यादृच्छिक परीक्षणों के आधार पर, अधिकांश कंपाइलर कोड उत्पन्न करते हैं जहां दो असाइनमेंट हस्तक्षेप नहीं करते हैं।

+1

मानकों के उन हिस्सों ने मुझे सिरदर्द दिया। मेरा वर्तमान पठन यह है कि इरादा यह है कि यह यूबी है (उदाहरण के लिए यह सी 11 में स्पष्ट है कि दो क्षेत्रों में दो फ़ील्ड को संशोधित करना एक कोर्स सिंक्रनाइज़ नहीं है), लेकिन 6.5 में भाषा दूसरे क्षेत्र की तरह बिट-फील्ड का उल्लेख करना भूल जाती है ऐसी जगहें जहां बिट-फ़ील्ड में विशेष हैंडलिंग होती है। – AProgrammer

+0

@AProgrammer: उपर्युक्त कोड में स्पष्ट तार्किक अर्थ है (लिखने के साथ अनुक्रमिक रूप से होता है, क्रमशः क्रम में होता है) और ऐसा कोई कारण नहीं है कि एक कंपाइलर जिसका लेखक नहीं जा रहा है, उस कोड को उत्पन्न नहीं करना चाहिए जो उस व्यवहार को उत्पन्न करता है सिंगल-थ्रेड केस में। क्या आप किसी भी व्यावहारिक कारण का सुझाव दे सकते हैं कि क्यों मानक के लेखक इसका उद्देश्य यूबी बन सकते हैं? – supercat

उत्तर

3

सी 11 नाम बिट फ़ील्ड को उसी स्मृति स्थान का हिस्सा बनने के लिए समझा जाता है। इस तरह के बिट फ़ील्ड परमाणु रूप से अद्यतन होने की गारंटी नहीं है, दूसरे शब्दों में यदि एक अद्यतन दूसरे के सामने स्पष्ट रूप से अनुक्रमित नहीं किया गया है तो व्यवहार अपरिभाषित है। 3.14 memory location तब भी एक विस्तृत स्पष्टीकरण है जब विभिन्न क्षेत्रों में दो क्षेत्रों को माना जा सकता है, इस प्रकार उनके अपडेट को स्वतंत्र रूप से माना जा सकता है।

आप अपने संरचना इस विचित्र दो बिट क्षेत्रों के बीच "स्मृति स्थान विभाजक" वहाँ है

struct S0 { 
     unsigned f0:4; 
     int :0; 
     signed f1:4; 
} l_62; 

ऐसी है कि संशोधित हैं, तो अपने कोड ठीक होने की गारंटी दी जाएगी।

सी 99 के लिए मामला अधिक जटिल लगता है, स्मृति स्थान की ऐसी विस्तृत अवधारणा नहीं है। लिनक्स कर्नेल मेलिंग सूची पर हाल ही में एक चर्चा में दावा किया गया था कि आमतौर पर बिट फ़ील्ड के सभी जोड़े के लिए उनमें से किसी को अपडेट करते समय परमाणुता की गारंटी होगी। उस चर्चा का प्रारंभिक बिंदु एक ऐसा मामला था जहां जीसीसी ने अप्रत्याशित तरीके से एक छोटे से क्षेत्र पड़ोसी को एक गैर-बिट क्षेत्र को प्रदूषित कर दिया जिससे नकली दुर्घटनाएं हुईं।

+2

उसी स्मृति स्थान को संशोधित करना सी 11 में डेटा रेस है, यह सुनिश्चित है। लेकिन जबकि 5.1.2.4/4 मेमोरी लोकेशन की बात करता है, 6.5/2 केवल स्केलर ऑब्जेक्ट्स की बात करता है। और मुझे यकीन नहीं है कि यह एक निरीक्षण है। सी ++ में संबंधित शब्द समान हैं, डेटा रेस लेकिन जाहिर है कि एक ही थ्रेड में एक अभिव्यक्ति के लिए यूबी नहीं है। – AProgrammer

+0

@AProgrammer: यह अधिकांश प्लेटफ़ॉर्म पर यह अनिवार्य रूप से अव्यवहारिक होगा कि एक साथ (अलग-अलग धागे) समान स्टोरेज तत्व में अलग-अलग बिटफिल्ड को लिखते हैं क्रमशः-अनुरूप फैशन में व्यवहार करते हैं। अधिकांश प्लेटफ़ॉर्म अनिवार्य रूप से शून्य लागत के लिए, गारंटी देते हैं कि एक फ़ील्ड के लिखने से दूसरे के साथ-साथ पढ़ने को प्रभावित नहीं होगा, लेकिन क्योंकि यह सभी प्लेटफॉर्म पर मुक्त नहीं होगा, मानक इसे अनिवार्य नहीं करता है। मुझे यह सुझाव देने के लिए कुछ भी नहीं दिख रहा है कि यौगिकों को एकल-थ्रेडेड मामलों को संभालने की उम्मीद नहीं की जानी चाहिए। – supercat

0

यहां असाइनमेंट स्ट्रक्चर सदस्यों के लिए है। तथ्य यह है कि वे एक ही भंडारण को साझा करने के लिए होते हैं, तर्क पर कोई प्रभाव नहीं पड़ता है। वास्तव में, आपने वास्तव में एक ही चीज़ को असाइनमेंट नहीं किया है।

बेशक, मैं एक भाषा वकील नहीं हूं।