असावधान लोगों के लिए जाल: unsigned int एक टाइम बम क्यों है?
\n\nहर C++ डेवलपर को देर-सबेर ऐसी स्थिति का सामना करना पड़ता है जहाँ संख्याएँ गुस्से में खरगोशों की तरह व्यवहार करती हैं - प्लस से जीरो पर अनंत रूप से कूदती हैं। बात कर रहे हैं unsigned int के ओवरफ़्लो की। अपने साइन वाले भाई (signed int) के विपरीत, C++ में unsigned का ओवरफ़्लो मानक द्वारा सख्ती से परिभाषित है - यह UB (undefined behavior) नहीं है। संख्या बस मॉड्यूलो 2N के अनुसार लपेट जाती है। लेकिन यह त्रुटि को कम घातक नहीं बनाता है।
कल्पना करें: आप खाते की शेष राशि, ऐरे में तत्वों की संख्या या टाइमर का संचालन समय गिन रहे हैं। एक आकस्मिक ओवरफ़्लो - और एप्लिकेशन का तर्क चरमरा जाता है। शीर्षक वाला प्रश्न "How do I detect unsigned integer overflow?" ने Stack Overflow पर हज़ारों बार देखा गया है, यह व्यर्थ नहीं है। आइए ओवरफ़्लो डिटेक्शन के तीन दृष्टिकोणों का विश्लेषण करें: भोले (लेकिन काम करने वाले) से लेकर पेशेवर तक।
\n\nमानक जाँचें काम क्यों नहीं करतीं?
\n\nपहली बात जो एक नौसिखिए के दिमाग में आती है:
\n\nunsigned int a = UINT_MAX;\nunsigned int b = 1;\nif (a + b < a) // भोली जाँच\n std::cout << "ओवरफ़्लो!";\n\nयह कोड काम करता है, लेकिन केवल जोड़ के लिए। गुणा, घटाव या मिश्रित प्रकारों के लिए तर्क टूट जाता है। इसके अलावा, कंपाइलर ऐसी जाँच को अनावश्यक मान सकता है और ऑप्टिमाइज़ेशन के दौरान इसे हटा सकता है, खासकर यदि प्रकार साइन वाले हों। जादू पर भरोसा न करें - स्पष्ट रूप से लिखें।
\n\nदृष्टिकोण #1: ऑपरेशन से पहले अंकगणित (Pre-check)
\n\nसबसे विश्वसनीय तरीका ऑपरेशन करने से पहले ओवरफ़्लो की संभावना की जाँच करना है। दो अहस्ताक्षरित संख्याओं को जोड़ने के लिए शर्त सरल है:
\n\nयदि a + b ओवरफ़्लो हो सकता है, तो a > (UINT_MAX - b)।
#include <climits>\n#include <iostream>\n\nbool will_add_overflow(unsigned int a, unsigned int b) {\n return a > UINT_MAX - b;\n}\n\nint main() {\n unsigned int x = 4000000000;\n unsigned int y = 500000000;\n \n if (will_add_overflow(x, y)) {\n std::cerr << "त्रुटि: जोड़ने पर ओवरफ़्लो!\\n";\n } else {\n std::cout << "परिणाम: " << x + y << "\\n";\n }\n return 0;\n}\n\nगुणा - अधिक जटिल
\nगुणा के लिए जाँच थोड़ी पेचीदा है: a > UINT_MAX / b (और शून्य से भाग देना न भूलें)।
bool will_mult_overflow(unsigned int a, unsigned int b) {\n if (b == 0) return false; // शून्य से गुणा - सुरक्षित\n return a > UINT_MAX / b;\n}\n\nलाभ: क्रॉस-प्लेटफ़ॉर्म, पूर्ण नियंत्रण, कोई छिपी निर्भरता नहीं।
\nनुकसान: प्रत्येक ऑपरेशन के लिए अलग-अलग फ़ंक्शन लिखने की आवश्यकता है। कोड बोझिल हो जाता है।
दृष्टिकोण #2: ऑपरेशन के बाद जाँच (Post-check)
\n\nC++ मानक गारंटी देता है कि unsigned प्रकारों के लिए ऑपरेशन का परिणाम (a + b) mod 2^N है। इसलिए हम ऑपरेशन कर सकते हैं और फिर जाँच सकते हैं कि मान "लपेटा" तो नहीं है।
#include <iostream>\n#include <limits>\n\ntemplate<typename T>\nbool add_overflow(T a, T b, T& result) {\n result = a + b;\n return result < a; // मुख्य ट्रिक\n}\n\nint main() {\n unsigned int res;\n if (add_overflow(4000000000u, 500000000u, res)) {\n std::cout << "ओवरफ़्लो दर्ज किया गया!\\n";\n } else {\n std::cout << "ठीक है: " << res << "\\n";\n }\n return 0;\n}\n\nमहत्वपूर्ण: यह ट्रिक तभी काम करती है जब a और b एक ही अहस्ताक्षरित प्रकार के हों। uint32_t के लिए - बढ़िया। unsigned int और int के मिश्रण के लिए - विफलता।
घटाव के लिए जाल
\nघटाव के लिए शर्त उलटी है: result > a।
template<typename T>\