C++ में जब बिल्ट-इन डेटा टाइप्स की वैध रेंज से बाहर मान असाइन किया जाता है, तो व्यवहार टाइप पर निर्भर करता है: अनसाइन्ड टाइप्स रैप-अराउंड करते हैं (well-defined), जबकि साइन्ड टाइप्स अनडिफाइंड बिहेवियर (UB) दिखाते हैं।
1. अनसाइन्ड टाइप्स: Well-Defined Wraparound
अनसाइन्ड इंटीजर्स मॉडुलो 2^N अंकगणित का पालन करते हैं (C++ स्टैंडर्ड द्वारा गारंटीड)।
#include <iostream>
#include <climits>
using namespace std;
int main() {
unsigned char uc = 255; // MAX: 255
cout << "uc = " << (int)uc << endl;
uc++; // 256 → 0 (wraparound)
cout << "uc++ = " << (int)uc << endl;
unsigned int ui = UINT_MAX;
cout << "UINT_MAX = " << ui << endl;
ui++; // 0 हो जाता है
cout << "UINT_MAX + 1 = " << ui << endl;
// लूप में समस्या
cout << "\nUnsigned loop issue:\n";
for (unsigned int i = 10; i >= 0; --i) {
cout << i << " ";
if (i == 0) break; // अनंत लूप से बचने के लिए!
}
cout << endl;
return 0;
}
आउटपुट
uc = 255 uc++ = 0 UINT_MAX = 4294967295 UINT_MAX + 1 = 0 Unsigned loop issue: 10 9 8 7 6 5 4 3 2 1 0
2. साइन्ड टाइप्स: Undefined Behavior (UB)
साइन्ड इंटीजर ओवरफ्लो अनडिफाइंड बिहेवियर है। कंपाइलर कुछ भी कर सकता है: रैपअराउंड, क्रैश, ऑप्टिमाइज़ अवे, आदि।
#include <iostream>
#include <climits>
using namespace std;
int main() {
int x = INT_MAX; // 2147483647
cout << "INT_MAX = " << x << endl;
// UB! कुछ भी हो सकता है
x = x + 1;
cout << "INT_MAX + 1 = " << x << " (UB - result unpredictable)\n";
// कंपाइलर इस चेक को ऑप्टिमाइज़ अवे कर सकता है!
if (x + 1 > x) {
cout << "x+1 > x is true\n";
} else {
cout << "x+1 > x is FALSE (due to UB optimization!)\n";
}
return 0;
}
आउटपुट (कंपाइलर-निर्भर)
INT_MAX = 2147483647 INT_MAX + 1 = -2147483648 (wraparound on this compiler) x+1 > x is FALSE (due to UB optimization!)
3. कैरेक्टर और बूल टाइप्स
#include <iostream>
using namespace std;
int main() {
// signed char: -128 से 127
signed char sc = 127;
cout << "sc = " << (int)sc;
sc++; // UB for signed!
cout << ", sc++ = " << (int)sc << endl;
// unsigned char: 0 से 255
unsigned char uc = 255;
uc++; // Well-defined: 0
cout << "uc++ = " << (int)uc << endl;
// bool: केवल 0 या 1 स्टोर कर सकता है
bool b = true;
b = b + true; // true (1) में प्रोमोट होता है, 1+1=2 → true (1)
cout << "bool true+true = " << b << endl;
// लूप इश्यू
cout << "\nBool loop:\n";
for (bool b = true; b <= 6; b++) {
cout << b << " "; // अनंत लूप: b हमेशा true रहता है!
if (b == false) break; // कभी नहीं पहुंचेगा
}
cout << endl;
return 0;
}
आउटपुट
sc = 127, sc++ = -128 (implementation-defined for signed overflow) uc++ = 0 bool true+true = 1 Bool loop: 1 1 1 1 1 ... (infinite loop)
4. फ्लोटिंग पॉइंट: इन्फिनिटी और NaN
#include <iostream>
#include <cmath>
#include <limits>
using namespace std;
int main() {
double d = 1e308;
cout << "d = " << d << endl;
d *= 10; // Overflow → infinity
cout << "d*10 = " << d << endl;
double inf = numeric_limits<double>::infinity();
double nan = numeric_limits<double>::quiet_NaN();
cout << "inf + 1 = " << inf + 1 << endl;
cout << "inf - inf = " << inf - inf << " (NaN)\n";
cout << "0.0 / 0.0 = " << 0.0/0.0 << " (NaN)\n";
cout << "sqrt(-1) = " << sqrt(-1) << " (NaN)\n";
return 0;
}
बचाव के उपाय
- चेक्ड अंकगणित:
<climits>के साथ मैनुअल चेक याstd::numeric_limits - सेफ लाइब्रेरी: Boost.SafeNumerics,
std::add_overflow(C++23 प्रस्तावित) - वाइडर टाइप: कैलकुलेशन के लिए
int64_tयाlong doubleउपयोग करें - कंपाइलर फ्लैग्स:
-ftrapv(GCC/Clang) साइन्ड ओवरफ्लो पर क्रैश करता है - अनसाइन्ड उपयोग करें जब निगेटिव मानों की आवश्यकता न हो (well-defined wraparound)
// सेफ एडिशन फंक्शन
bool safeAdd(int a, int b, int &result) {
if (b > 0 && a > INT_MAX - b) return false; // Overflow
if (b < 0 && a < INT_MIN - b) return false; // Underflow
result = a + b;
return true;
}