प्रसंग
हम सी कोड को पोर्ट कर रहे हैं जो मूल रूप से PIC माइक्रोकंट्रोलर के लिए 8-बिट सी कंपाइलर का उपयोग करके संकलित किया गया था। एक सामान्य मुहावरे का इस्तेमाल किया गया था, जो अहस्ताक्षरित वैश्विक चर (उदाहरण के लिए, त्रुटि काउंटर) को वापस शून्य पर लुढ़कने से रोकने के लिए इस्तेमाल किया गया है:
if(~counter) counter++;
यहाँ बिटवाइज़ ऑपरेटर सभी बिट्स को बदल देता है और यदि केवल counter
अधिकतम मान से कम है तो कथन सही है। महत्वपूर्ण रूप से, यह चर आकार की परवाह किए बिना काम करता है।
मुसीबत
अब हम GCC का उपयोग करके 32-बिट ARM प्रोसेसर को लक्षित कर रहे हैं। हमने देखा है कि एक ही कोड अलग-अलग परिणाम देता है। अब तक हम बता सकते हैं, ऐसा लगता है कि बिटवाइज़ सप्लीमेंट ऑपरेशन एक ऐसा मूल्य देता है जो एक अलग आकार है जितना हम उम्मीद करेंगे। इसे पुन: प्रस्तुत करने के लिए, हम जीसीसी में संकलित करते हैं:
uint8_t i = 0;
int sz;
sz = sizeof(i);
printf("Size of variable: %d\n", sz); // Size of variable: 1
sz = sizeof(~i);
printf("Size of result: %d\n", sz); // Size of result: 4
आउटपुट की पहली पंक्ति में, हमें वह मिलता है जिसकी हम अपेक्षा करते हैं: i
1 बाइट। हालांकि, बिटवाइज़ का पूरक i
वास्तव में चार बाइट्स है जो एक समस्या का कारण बनता है क्योंकि इसके साथ तुलना अब अपेक्षित परिणाम नहीं देगी। उदाहरण के लिए, यदि कर रहा है (जहां i
एक ठीक से शुरू किया गया है uint8_t
):
if(~i) i++;
हम i
0xFF से 0x00 तक "रैप अराउंड" देखेंगे । यह व्यवहार GCC के साथ तुलना में अलग है जब यह पिछले कंपाइलर और 8-बिट PIC माइक्रोकंट्रोलर में काम करने के लिए इस्तेमाल किया गया था।
हम जानते हैं कि हम इस तरह से कास्टिंग करके इसे हल कर सकते हैं:
if((uint8_t)~i) i++;
या द्वारा
if(i < 0xFF) i++;
हालाँकि इन दोनों वर्कअराउंड में, चर का आकार ज्ञात होना चाहिए और सॉफ़्टवेयर डेवलपर के लिए त्रुटि-प्रवण है। इस प्रकार की ऊपरी सीमा की जाँच पूरे कोडबेस में होती है। चर (जैसे।, uint16_t
और unsigned char
आदि) के कई आकार हैं और इन्हें अन्यथा काम करने वाले कोडबेस में बदलना ऐसी चीज नहीं है जिसे हम आगे देखना चाहते हैं।
सवाल
क्या समस्या के बारे में हमारी समझ सही है, और क्या इसको हल करने के लिए विकल्प उपलब्ध हैं जिन्हें प्रत्येक मामले में दोबारा जाने की आवश्यकता नहीं है जहाँ हमने इस मुहावरे का उपयोग किया है? क्या हमारी धारणा सही है, कि बिटवाइज़ सप्लीमेंट जैसे ऑपरेशन को एक परिणाम देना चाहिए जो कि ऑपरेंड के समान आकार का हो? ऐसा लगता है कि प्रोसेसर आर्किटेक्चर के आधार पर यह टूट जाएगा। मुझे लगता है कि मैं पागल गोलियां ले रहा हूं और सी को इससे थोड़ा अधिक पोर्टेबल होना चाहिए। फिर, इस बारे में हमारी समझ गलत हो सकती है।
सतह पर यह एक बहुत बड़ा मुद्दा नहीं लग सकता है, लेकिन पहले से काम कर रहे मुहावरे का इस्तेमाल सैकड़ों स्थानों पर किया जाता है और हम महंगे बदलावों के साथ आगे बढ़ने से पहले इसे समझने के लिए उत्सुक हैं।
नोट: यहां एक समान प्रतीत होता है, लेकिन सटीक डुप्लिकेट प्रश्न यहां नहीं है: चार्ट पर बिटवाइज़ ऑपरेशन 32 बिट परिणाम देता है
मुझे वहां चर्चा किए गए मुद्दे के वास्तविक क्रैक्स को नहीं देखा, अर्थात्, एक बिटवाइज़ पूरक का परिणाम आकार ऑपरेटर में पारित होने की तुलना में अलग है।