पहली नज़र में, यह प्रश्न डुप्लिकेट की तरह लग सकता है कि पूर्णांक ओवरफ़्लो का पता कैसे लगाया जाए? , हालांकि यह वास्तव में काफी अलग है।
मैंने पाया है कि एक अहस्ताक्षरित पूर्णांक अतिप्रवाह का पता लगाने के दौरान बहुत मामूली है, सी / सी ++ में एक हस्ताक्षरित अतिप्रवाह का पता लगाना वास्तव में ज्यादातर लोगों की तुलना में अधिक कठिन है।
सबसे स्पष्ट, अभी तक अनुभवहीन, इसे करने का तरीका कुछ इस तरह होगा:
int add(int lhs, int rhs)
{
int sum = lhs + rhs;
if ((lhs >= 0 && sum < rhs) || (lhs < 0 && sum > rhs)) {
/* an overflow has occurred */
abort();
}
return sum;
}
इसके साथ समस्या यह है कि सी मानक के अनुसार, हस्ताक्षरित पूर्णांक अतिप्रवाह अपरिभाषित व्यवहार है। दूसरे शब्दों में, मानक के अनुसार, जैसे ही आप भी एक हस्ताक्षरित अतिप्रवाह का कारण बनते हैं, आपका कार्यक्रम ठीक वैसे ही अमान्य है जैसे कि आपने एक अशक्त सूचक को छोड़ दिया हो। इसलिए आप अपरिभाषित व्यवहार का कारण नहीं बन सकते हैं, और फिर इस तथ्य के बाद अतिप्रवाह का पता लगाने का प्रयास करें, जैसा कि ऊपर की स्थिति के बाद उदाहरण में हुआ है।
भले ही उपरोक्त चेक कई संकलक पर काम करने की संभावना है, आप इस पर भरोसा नहीं कर सकते। वास्तव में, क्योंकि C मानक कहता है कि साइन इन किया गया पूर्णांक ओवरफ़्लो अपरिभाषित है, इसलिए कुछ कंपाइलर (जैसे GCC) ऑप्टिमाइज़ फ़्लैग सेट होने पर उपरोक्त चेक को ऑप्टिमाइज़ कर देंगे , क्योंकि कंपाइलर हस्ताक्षरित ओवरफ़्लो असंभव है। यह पूरी तरह से अतिप्रवाह की जांच करने के प्रयास को तोड़ देता है।
इसलिए, अतिप्रवाह की जांच करने का एक और संभावित तरीका होगा:
int add(int lhs, int rhs)
{
if (lhs >= 0 && rhs >= 0) {
if (INT_MAX - lhs <= rhs) {
/* overflow has occurred */
abort();
}
}
else if (lhs < 0 && rhs < 0) {
if (lhs <= INT_MIN - rhs) {
/* overflow has occurred */
abort();
}
}
return lhs + rhs;
}
यह अधिक आशाजनक लगता है, क्योंकि हम वास्तव में दो पूर्णांकों को एक साथ नहीं जोड़ते हैं जब तक कि हम पहले से सुनिश्चित नहीं करते हैं कि इस तरह के ऐड का प्रदर्शन अतिप्रवाह नहीं होगा। इस प्रकार, हम किसी भी अपरिभाषित व्यवहार का कारण नहीं है।
हालाँकि, यह समाधान दुर्भाग्य से प्रारंभिक समाधान की तुलना में बहुत कम कुशल है, क्योंकि आपको परीक्षण करने के लिए एक घटाव ऑपरेशन करना होगा, यदि आपका अतिरिक्त ऑपरेशन काम करेगा। और भले ही आपको इस (छोटे) प्रदर्शन के बारे में परवाह न हो, फिर भी मैं पूरी तरह आश्वस्त नहीं हूं कि यह समाधान पर्याप्त है। अभिव्यक्ति lhs <= INT_MIN - rhs
बिल्कुल उसी तरह की लगती है, जिस प्रकार की संकलक दूर अनुकूलन कर सकता है, यह सोचकर कि हस्ताक्षरित अतिप्रवाह असंभव है।
तो क्या यहां बेहतर समाधान है? कुछ जो 1 को गारंटी देता है) अपरिभाषित व्यवहार का कारण नहीं बनता है, और 2) कंपाइलर को ओवरफ्लो चेक को अनुकूलित करने का अवसर प्रदान नहीं करता है? मैं सोच रहा था कि दोनों ऑपरेंड को बिना बताए कास्टिंग करके और अपने खुद के दो-पूरक अंकगणित को रोल करके चेक करने का कोई तरीका हो सकता है, लेकिन मुझे यकीन नहीं है कि यह कैसे करना है।