c++ - पूर्णांक ओवरफ़्लो का पता कैसे लगाएं?




integer-overflow (20)

You can't access the overflow flag from C/C++.

I don't agree with this. You could write some inline asm and use a jo (jump overflow) instruction assuming you are on x86 to trap the overflow. Of course you code would no longer be portable to other architectures.

look at info as and info gcc .

मैं बी = सी के सभी समाधान खोजने के लिए सी ++ में एक प्रोग्राम लिख रहा था, जहां , बी और सी एक साथ सभी अंक 0-9 का उपयोग करते हैं। कार्यक्रम और बी के मानों से ढंका हुआ था, और अंकों की स्थिति संतुष्ट होने पर यह जांचने के लिए प्रत्येक बार बी , बी और बी पर अंक-गिनती दिनचर्या चलाती थी।

हालांकि, जब बी बी पूर्णांक सीमा को ओवरफ्लो करता है तो नकली समाधान उत्पन्न किए जा सकते हैं। मैं कोड का उपयोग कर इस के लिए जांच कर समाप्त हुआ:

unsigned long b, c, c_test;
...
c_test=c*b;         // Possible overflow
if (c_test/b != c) {/* There has been an overflow*/}
else c=c_test;      // No overflow

अतिप्रवाह के लिए परीक्षण का एक बेहतर तरीका है? मुझे पता है कि कुछ चिप्स में एक आंतरिक ध्वज होता है जो अतिप्रवाह होने पर सेट होता है, लेकिन मैंने कभी इसे सी या सी ++ के माध्यम से नहीं देखा है।


आप सी / सी ++ से अतिप्रवाह ध्वज तक नहीं पहुंच सकते हैं।

कुछ कंपाइलर आपको कोड में जाल निर्देश डालने की अनुमति देते हैं। जीसीसी पर विकल्प है -फ्रैपव (लेकिन मुझे यह मानना ​​है कि मैंने इसका कभी भी उपयोग नहीं किया है। पोस्ट करने के बाद इसे जांच लेंगे)।

एकमात्र पोर्टेबल और कंपाइलर स्वतंत्र चीज जो आप कर सकते हैं वह है कि आप अपने आप ओवरफ्लो की जांच कर सकें। जैसे आपने अपने उदाहरण में किया था।

संपादित करें:

बस चेक किया गया: -फ्रैपटव सबसे पुराना जीसीसी का उपयोग कर x86 पर कुछ भी नहीं करता है। मान लीजिए कि यह पुराने संस्करण से या किसी अन्य वास्तुकला के लिए विशिष्ट है। मैंने उम्मीद की थी कि प्रत्येक अतिरिक्त के बाद कंपाइलर एक आईएनटीओ ओपोड डालें। दुर्भाग्य से यह ऐसा नहीं करता है।


चेतावनी: -O2 साथ संकलन करते समय जीसीसी एक अतिप्रवाह जांच को अनुकूलित कर सकता है। विकल्प -Wall आपको कुछ मामलों में चेतावनी देगा

if (a + b < a) { /* deal with overflow */ }

लेकिन इस उदाहरण में नहीं:

b = abs(a);
if (b < 0) { /* deal with overflow */ }

सीईआरटी पेपर में वर्णित होने से पहले अतिप्रवाह की जांच करना एकमात्र सुरक्षित तरीका है, और यह व्यवस्थित रूप से उपयोग करने के लिए अविश्वसनीय रूप से कठिन होगा।

-fwrapv साथ संकलन समस्या हल करता है लेकिन कुछ अनुकूलन अक्षम करता है।

हमें बेहद बेहतर समाधान की आवश्यकता है। मुझे लगता है कि संकलक को डिफ़ॉल्ट रूप से चेतावनी देना चाहिए जब एक अनुकूलन नहीं हो रहा है जो अतिप्रवाह पर निर्भर करता है। वर्तमान स्थिति संकलक को ओवरफ्लो चेक को अनुकूलित करने की अनुमति देती है, जो मेरी राय में अस्वीकार्य है।


प्रश्न के लिए एक "गैर पोर्टेबल" समाधान यहां दिया गया है। इंटेल x86 और x64 CPUs में तथाकथित EFLAGS- रजिस्टर ( http://en.wikipedia.org/wiki/EFLAGS ) है, जो प्रत्येक पूर्णांक अंकगणितीय ऑपरेशन के बाद प्रोसेसर द्वारा भरा जाता है। मैं यहां एक विस्तृत विवरण छोड़ दूंगा। प्रासंगिक झंडे "ओवरफ्लो" ध्वज (मुखौटा 0x800) और "कैरी" ध्वज (मुखौटा 0x1) हैं। उन्हें सही ढंग से समझने के लिए, किसी को यह विचार करना चाहिए कि क्या ऑपरेशंस हस्ताक्षरित या हस्ताक्षरित प्रकार के हैं।

यहां सी / सी ++ से झंडे की जांच करने का एक व्यावहारिक तरीका है। निम्न कोड विजुअल स्टूडियो 2005 या नए (32 और 64 बिट दोनों) पर काम करेगा, साथ ही जीएनयू सी / सी ++ 64 बिट पर भी काम करेगा।

#include <cstddef>
#if defined( _MSC_VER )
#include <intrin.h>
#endif

inline size_t query_intel_x86_eflags( const size_t query_bit_mask )
{
#if defined( _MSC_VER )
    return __readeflags() & query_bit_mask;
#elif defined( __GNUC__ )
    // this code will work only on 64-bit GNU-C machines;
    // Tested and does NOT work with Intel C++ 10.1!
    size_t eflags;
    __asm__ __volatile__(
        "pushfq \n\t"
        "pop %%rax\n\t"
        "movq %%rax, %0\n\t"
        :"=r"(eflags)
        :
        :"%rax"
        );
    return eflags & query_bit_mask;
#else
#pragma message("No inline assembly will work with this compiler!")
    return 0;
#endif
}

int main(int argc, char **argv)
{
    int x = 1000000000;
    int y = 20000;
    int z = x * y;
    int f = query_intel_x86_eflags( 0x801 );
    printf( "%X\n", f );
}

यदि ऑपरेंड ओवरफ्लो के बिना गुणा किए गए थे, तो आपको query_intel_eflags (0x801) से 0 का रिटर्न मान मिलेगा, यानी न तो वाह और न ही ओवरफ्लो झंडे सेट किए गए हैं। मुख्य उदाहरण () के प्रदान किए गए उदाहरण कोड में, एक अतिप्रवाह होता है और दोनों झंडे 1 पर सेट होते हैं। यह चेक किसी और गणना को इंगित नहीं करता है, इसलिए यह काफी तेज़ होना चाहिए।


मुझे लगता है कि आप हस्ताक्षरित पूर्णांक का उपयोग कर रहे हैं। परिभाषा के अनुसार, सी में (सी ++ के बारे में नहीं पता), हस्ताक्षरित अंकगणित अतिप्रवाह नहीं है ... इसलिए, कम से कम सी के लिए, आपका बिंदु म्यूट है :)

हस्ताक्षर किए गए पूर्णांक के साथ, एक बार ओवरफ़्लो हो जाने के बाद, अपरिभाषित व्यवहार हुआ है और आपका प्रोग्राम कुछ भी कर सकता है (उदाहरण के लिए: परीक्षण अनिवार्य रूप से प्रस्तुत करें)।

#include <limits.h>
int a = <something>;
int x = <something>;
a += x;              /* UB */
if (a < 0) {         /* unreliable test */
  /* ... */
}

एक अनुरूप प्रोग्राम बनाने के लिए आपको अतिप्रवाह उत्पन्न करने से पहले अतिप्रवाह के लिए परीक्षण करने की आवश्यकता है। विधि का उपयोग बिना हस्ताक्षर किए गए पूर्णांक के साथ भी किया जा सकता है

// for addition
#include <limits.h>
int a = <something>;
int x = <something>;
if ((x > 0) && (a > INT_MAX - x)) /* `a + x` would overflow */;
if ((x < 0) && (a < INT_MIN - x)) /* `a + x` would underflow */;
// for subtraction
#include <limits.h>
int a = <something>;
int x = <something>;
if ((x < 0) && (a > INT_MAX + x)) /* `a - x` would overflow */;
if ((x > 0) && (a < INT_MIN + x)) /* `a - x` would underflow */;
// for multiplication
#include <limits.h>
int a = <something>;
int x = <something>;
if (a > INT_MAX / x) /* `a * x` would overflow */;
if ((a < INT_MIN / x)) /* `a * x` would underflow */;
// there may be need to check for -1 for two's complement machines
if ((a == -1) && (x == INT_MIN)) /* `a * x` can overflow */
if ((x == -1) && (a == INT_MIN)) /* `a * x` (or `a / x`) can overflow */

विभाजन के लिए ( INT_MIN और -1 विशेष मामले को छोड़कर) INT_MIN या INT_MAX पर जाने की कोई संभावना नहीं है।


मैं देखता हूं कि बहुत से लोगों ने अतिप्रवाह के बारे में सवाल का जवाब दिया, लेकिन मैं उनकी मूल समस्या को संबोधित करना चाहता था। उन्होंने कहा कि समस्या बी = सी को ढूंढना था जैसे कि सभी अंक दोहराने के बिना उपयोग किए जाते हैं। ठीक है, इस पोस्ट में उन्होंने यही नहीं पूछा, लेकिन मुझे अभी भी लगता है कि समस्या के ऊपरी बाउंड का अध्ययन करना आवश्यक था और निष्कर्ष निकाला था कि उसे किसी ओवरफ्लो की गणना या पहचान करने की आवश्यकता नहीं होगी (नोट: मैं कुशल नहीं हूं गणित में इसलिए मैंने कदम से यह कदम उठाया, लेकिन अंतिम परिणाम इतना आसान था कि इसका एक सरल सूत्र हो सकता है)।

मुख्य बिंदु यह है कि ऊपरी बाउंड जो किसी भी समस्या के लिए आवश्यक है, बी या सी 98.765.432 है। वैसे भी, तुच्छ और गैर तुच्छ भागों में समस्या को विभाजित करके शुरू करना:

  • एक्स 0 == 1 (9, 8, 7, 6, 5, 4, 3, 2 के सभी क्रमपरिवर्तन समाधान हैं)
  • एक्स 1 == एक्स (कोई समाधान संभव नहीं है)
  • 0 बी == 0 (कोई समाधान संभव नहीं है)
  • 1 बी == 1 (कोई समाधान संभव नहीं है)
  • एक बी , ए> 1, बी> 1 (गैर तुच्छ)

अब हमें यह दिखाने की ज़रूरत है कि कोई अन्य समाधान संभव नहीं है और केवल क्रमपरिवर्तन मान्य हैं (और फिर उन्हें मुद्रित करने के लिए कोड छोटा है)। हम ऊपरी बाउंड पर वापस जाते हैं। दरअसल ऊपरी सीमा सी ≤ 98.765.432 है। यह ऊपरी बाध्य है क्योंकि यह 8 अंकों के साथ सबसे बड़ी संख्या है (प्रत्येक ए के लिए 10 अंक कुल शून्य 1 और बी)। यह ऊपरी सीमा केवल सी के लिए है क्योंकि घातीय वृद्धि के कारण ए और बी के लिए सीमाएं बहुत कम होनी चाहिए, क्योंकि हम गणना कर सकते हैं, 2 से ऊपरी बाउंड में भिन्न बी:

    9938.08^2 == 98765432
    462.241^3 == 98765432
    99.6899^4 == 98765432
    39.7119^5 == 98765432
    21.4998^6 == 98765432
    13.8703^7 == 98765432
    9.98448^8 == 98765432
    7.73196^9 == 98765432
    6.30174^10 == 98765432
    5.33068^11 == 98765432
    4.63679^12 == 98765432
    4.12069^13 == 98765432
    3.72429^14 == 98765432
    3.41172^15 == 98765432
    3.15982^16 == 98765432
    2.95305^17 == 98765432
    2.78064^18 == 98765432
    2.63493^19 == 98765432
    2.51033^20 == 98765432
    2.40268^21 == 98765432
    2.30883^22 == 98765432
    2.22634^23 == 98765432
    2.15332^24 == 98765432
    2.08826^25 == 98765432
    2.02995^26 == 98765432
    1.97741^27 == 98765432

नोटिस, उदाहरण के लिए आखिरी पंक्ति: यह कहता है कि 1.97 ^ 27 ~ 98 एम। तो, उदाहरण के लिए, 1 ^ 27 == 1 और 2 ^ 27 == 134.217.728 और यह कोई समाधान नहीं है क्योंकि इसमें 9 अंक हैं (2> 1.97 इसलिए यह वास्तव में परीक्षण किए जाने से बड़ा है)। जैसा कि देखा जा सकता है, ए और बी परीक्षण के लिए उपलब्ध संयोजन वास्तव में छोटे हैं। बी == 14 के लिए, हमें 2 और 3 का प्रयास करने की आवश्यकता है। बी == 3 के लिए, हम 2 से शुरू होते हैं और 462 पर रुकते हैं। सभी परिणाम ~ 98 एम से कम होने के लिए दिए जाते हैं।

अब उपर्युक्त सभी संयोजनों का परीक्षण करें और उन लोगों की तलाश करें जो किसी भी अंक को दोहराते नहीं हैं:

    ['0', '2', '4', '5', '6', '7', '8'] 2^84 = 7056
    ['1', '2', '3', '4', '5', '8', '9'] 2^59 = 3481
    ['0', '1', '2', '3', '4', '5', '8', '9'] 2^59 = 3481 (+leading zero)
    ['1', '2', '3', '5', '8'] 3^8 = 512
    ['0', '1', '2', '3', '5', '8'] 3^8 = 512 (+leading zero)
    ['1', '2', '4', '6'] 2^4 = 16
    ['0', '1', '2', '4', '6'] 2^4 = 16 (+leading zero)
    ['1', '2', '4', '6'] 4^2 = 16
    ['0', '1', '2', '4', '6'] 4^2 = 16 (+leading zero)
    ['1', '2', '8', '9'] 2^9 = 81
    ['0', '1', '2', '8', '9'] 2^9 = 81 (+leading zero)
    ['1', '3', '4', '8'] 4^3 = 81
    ['0', '1', '3', '4', '8'] 4^3 = 81 (+leading zero)
    ['2', '3', '6', '7', '9'] 6^3 = 729
    ['0', '2', '3', '6', '7', '9'] 6^3 = 729 (+leading zero)
    ['2', '3', '8'] 3^2 = 8
    ['0', '2', '3', '8'] 3^2 = 8 (+leading zero)
    ['2', '3', '9'] 2^3 = 9
    ['0', '2', '3', '9'] 2^3 = 9 (+leading zero)
    ['2', '4', '6', '8'] 2^8 = 64
    ['0', '2', '4', '6', '8'] 2^8 = 64 (+leading zero)
    ['2', '4', '7', '9'] 2^7 = 49
    ['0', '2', '4', '7', '9'] 2^7 = 49 (+leading zero)

उनमें से कोई भी समस्या से मेल नहीं खाता (जिसे '0', '1', ..., '9' की अनुपस्थिति से भी देखा जा सकता है)।

उदाहरण कोड जो हल करता है इसे हल करता है। यह भी ध्यान दें कि पायथन में लिखा गया है, न कि इसे मनमाने ढंग से सटीक पूर्णांक की आवश्यकता है (कोड 98 मिलियन से बड़ा कुछ भी गणना नहीं करता है), लेकिन क्योंकि हमें पता चला कि परीक्षण की मात्रा इतनी छोटी है कि हमें उच्च स्तर की भाषा का उपयोग करना चाहिए इसके अंतर्निहित कंटेनरों और पुस्तकालयों का उपयोग करें (यह भी ध्यान दें: कोड में 28 लाइनें हैं)।

    import math

    m = 98765432
    l = []
    for i in xrange(2, 98765432):
        inv = 1.0/i
        r = m**inv
        if (r < 2.0): break
        top = int(math.floor(r))
        assert(top <= m)

        for j in xrange(2, top+1):
            s = str(i) + str(j) + str(j**i)
            l.append((sorted(s), i, j, j**i))
            assert(j**i <= m)

    l.sort()
    for s, i, j, ji in l:
        assert(ji <= m)
        ss = sorted(set(s))
        if s == ss:
            print '%s %d^%d = %d' % (s, i, j, ji)

        # Try with non significant zero somewhere
        s = ['0'] + s
        ss = sorted(set(s))
        if s == ss:
            print '%s %d^%d = %d (+leading zero)' % (s, i, j, ji)

यह निर्धारित करने का एक तरीका है कि संचालन में सबसे महत्वपूर्ण एक-बिट्स और थोड़ा बुनियादी बाइनरी-गणित ज्ञान की स्थिति का उपयोग करके एक ऑपरेशन बहने की संभावना है या नहीं।

इसके अलावा, किसी भी दो ऑपरेंड का परिणाम सबसे अधिक ऑपरेंड के उच्चतम एक-बिट से अधिक (अधिकतर) होगा। उदाहरण के लिए:

bool addition_is_safe(uint32_t a, uint32_t b) {
    size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
    return (a_bits<32 && b_bits<32);
}

गुणा के लिए, किसी भी दो ऑपरेंड के परिणामस्वरूप (अधिकतर) ऑपरेटरों के बिट्स का योग होगा। उदाहरण के लिए:

bool multiplication_is_safe(uint32_t a, uint32_t b) {
    size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
    return (a_bits+b_bits<=32);
}

इसी तरह, आप b की शक्ति के परिणाम के अधिकतम आकार का अनुमान लगा सकते हैं:

bool exponentiation_is_safe(uint32_t a, uint32_t b) {
    size_t a_bits=highestOneBitPosition(a);
    return (a_bits*b<=32);
}

(निश्चित रूप से अपने लक्ष्य पूर्णांक के लिए बिट्स की संख्या का चयन करें।)

मुझे किसी संख्या में उच्चतम एक-बिट की स्थिति निर्धारित करने का सबसे तेज़ तरीका नहीं है, यहां एक क्रूर-बल विधि है:

size_t highestOneBitPosition(uint32_t a) {
    size_t bits=0;
    while (a!=0) {
        ++bits;
        a>>=1;
    };
    return bits;
}

यह सही नहीं है, लेकिन यह आपको एक अच्छा विचार देगा कि आप ऑपरेशन करने से पहले कोई भी दो संख्याएं बहती हैं या नहीं। मुझे नहीं पता कि यह highestOneBitPosition फ़ंक्शन में लूप की वजह से आपके द्वारा सुझाए गए परिणामों की जांच करने से तेज़ होगा, लेकिन यह हो सकता है (विशेष रूप से यदि आपको पता था कि पहले से ही कितने बिट्स ऑपरेंड में थे)।


सबसे आसान तरीका है अपने unsigned long एस को unsigned long long में परिवर्तित करना, अपनी गुणा करें, और परिणाम की तुलना 0x100000000LL से करें।

आपको शायद यह पता चलेगा कि विभाजन के मुकाबले यह अधिक कुशल है जैसा आपने अपने उदाहरण में किया है।

ओह, और यह सी और सी ++ दोनों में काम करेगा (जैसा कि आपने दोनों के साथ प्रश्न टैग किया है)।

बस glibc मैनुअल पर एक नज़र डालने जा रहा है। FPE_INTOVF_TRAP के हिस्से के रूप में एक पूर्णांक ओवरफ्लो जाल ( FPE_INTOVF_TRAP ) का SIGFPE । मैनुअल में गंदे बिट्स के अलावा यह आदर्श होगा:

FPE_INTOVF_TRAP इंटीजर ओवरफ़्लो (एक सी प्रोग्राम में असंभव है जब तक कि आप एक हार्डवेयर-विशिष्ट फैशन में ओवरफ़्लो फँसाने को सक्षम नहीं करते)।

वास्तव में एक शर्म की बात है।


हालांकि यह दो साल हो गया है, मुझे लगा कि मैं कम से कम जोड़ों के लिए ओवरफ्लो का पता लगाने के लिए वास्तव में तेज़ तरीके से अपना पेनथवर्थ जोड़ सकता हूं, जो गुणा, विभाजन और शक्ति के लिए नेतृत्व दे सकता है

विचार यह है कि वास्तव में प्रोसेसर सिर्फ मूल्य को शून्य पर वापस जाने देगा और सी / सी ++ किसी विशिष्ट प्रोसेसर से सारणीबद्ध है, आप यह कर सकते हैं:

uint32_t x, y;
uint32_t value = x + y;
bool overflow = value < (x | y);

यह दोनों सुनिश्चित करता है कि यदि एक ऑपरेंड शून्य है और कोई नहीं है, तो अतिप्रवाह का गलत पता नहीं लगाया जाएगा, और पहले सुझाए गए अनुसार बहुत सारे / एक्सओआर / एंड / टेस्ट ऑपरेशंस की तुलना में काफी तेज़ है।

संपादित करें : जैसा कि बताया गया है, यह दृष्टिकोण हालांकि अन्य विस्तृत तरीकों से बेहतर है, फिर भी अनुकूलन योग्य है। निम्नलिखित ऑप्टिमाइज़ेशन वाले मूल कोड का पुनरीक्षण है:

uint32_t x, y;
uint32_t value = x + y;
bool overflow = value < x; // Alternatively "value < y" should also work

क्लैंग 3.4+ और जीसीसी 5+ ऑफर अंकगणित बिल्टिन की पेशकश की। वे इस समस्या के लिए एक बहुत तेज़ समाधान प्रदान करते हैं, खासकर जब बिट-परीक्षण सुरक्षा जांच की तुलना में।

ओपी के सवाल में उदाहरण के लिए, यह इस तरह काम करेगा:

unsigned long b, c, c_test;
if (__builtin_umull_overflow(b, c, &c_test))
{
    // returned non-zero: there has been an overflow
}
else
{
    // return zero: there hasn't been an overflow
}

c_test प्रलेखन यह निर्दिष्ट नहीं करता है कि अगर ओवरफ्लो हुआ तो c_test में अतिप्रवाह परिणाम होता है, लेकिन जीसीसी दस्तावेज कहता है कि यह करता है। यह देखते हुए कि ये दोनों __builtin संगत होने की तरह हैं, यह संभवतः यह मानना ​​सुरक्षित है कि __builtin भी काम करता है।

प्रत्येक अंकगणितीय ऑपरेशन के लिए __builtin है जो int आकार, लंबे आकार और लंबे लंबे आकार के लिए हस्ताक्षरित और हस्ताक्षरित रूपों के साथ अतिप्रवाह (अतिरिक्त, घटाव, गुणा) कर सकता है। नाम के लिए वाक्यविन्यास __builtin_[us](operation)(l?l?)_overflow :

  • हस्ताक्षरित के लिए आप हस्ताक्षरित या s लिए;
  • ऑपरेशन add , sub या mul ;
  • कोई l प्रत्यय का मतलब है कि ऑपरेंड int हैं; एक l long मतलब है; दो l मतलब long long

तो एक चेक हस्ताक्षरित लंबे पूर्णांक के अतिरिक्त, यह __builtin_saddl_overflow होगा। पूर्ण सूची क्लैंग दस्तावेज़ पृष्ठ पर पाई जा सकती है।

जीसीसी 5+ और __builtin_add_overflow अतिरिक्त रूप से जेनेरिक __builtin_add_overflow प्रदान करते हैं जो मानों के प्रकार को निर्दिष्ट किए बिना काम करते हैं: __builtin_add_overflow , __builtin_sub_overflow और __builtin_mul_overflow । ये int से छोटे प्रकार के प्रकार पर भी काम करते हैं।

प्लेटफॉर्म के लिए सबसे अच्छा क्या है जो बिल्टिन कम है। X86 पर, वे ले जाने, ओवरफ्लो और साइन झंडे की जांच करते हैं।

विजुअल स्टूडियो के cl.exe में प्रत्यक्ष समकक्ष नहीं हैं। बिना हस्ताक्षर किए गए जोड़ों और <intrin.h> , <intrin.h> सहित आप addcarry_uNN और subborrow_uNN (जहां एनएन बिट्स की संख्या है, जैसे addcarry_u8 या subborrow_u64 ) का उपयोग करने की अनुमति देगा। उनका हस्ताक्षर थोड़ा उलझन में है:

unsigned char _addcarry_u32(unsigned char c_in, unsigned int src1, unsigned int src2, unsigned int *sum);
unsigned char _subborrow_u32(unsigned char b_in, unsigned int src1, unsigned int src2, unsigned int *diff);

c_in / b_in इनपुट पर b_in / उधार झंडा है, वापसी मूल्य आउटपुट पर b_in / उधार है। यह हस्ताक्षरित संचालन या गुणाओं के लिए समकक्ष प्रतीत नहीं होता है।

अन्यथा, विंडोज के लिए क्लैंग अब उत्पादन-तैयार है (क्रोम के लिए पर्याप्त है), ताकि यह भी एक विकल्प हो।


mozilla::CheckedInt<T> provides overflow-checked integer math for integer type T (using compiler intrinsics on clang and gcc as available). The code is under MPL 2.0 and depends on three ( IntegerTypeTraits.h , Attributes.h and Compiler.h ) other header-only non-standard library headers plus Mozilla-specific assertion machinery . You probably want to replace the assertion machinery if you import the code.


क्लैंग अब हस्ताक्षरित और हस्ताक्षरित पूर्णांक दोनों के लिए गतिशील ओवरफ्लो चेक का समर्थन करता है। देखें -fsanitize=integer स्विच। अभी के लिए यह डीबग उद्देश्य के लिए पूरी तरह से समर्थित गतिशील ओवरफ्लो जांच के साथ केवल एक सी ++ संकलक है।


A clean way to do it would be to override all operators (+ and * in particular) and check for an overflow before perorming the operations.


Another interesting tool: http://embed.cs.utah.edu/ioc/

This is a patched clang compiler, which adds checks to the code at compile time. So you get output looking like this:

CLANG ARITHMETIC UNDEFINED at <add.c, (9:11)> :
Op: +, Reason : Signed Addition Overflow, 
BINARY OPERATION: left (int32): 2147483647 right (int32): 1

CERT has developed a new approach to detecting and reporting signed integer overflow, unsigned integer wrapping, and integer truncation using the "as-if" infinitely ranged (AIR) integer model. CERT has published a technical report describing the model and produced a working prototype based on GCC 4.4.0 and GCC 4.5.0.

The AIR integer model either produces a value equivalent to one that would have been obtained using infinitely ranged integers or results in a runtime constraint violation. Unlike previous integer models, AIR integers do not require precise traps, and consequently do not break or inhibit most existing optimizations.


Calculate the results with doubles. They have 15 significant digits. Your requirement has a hard upper bound on c of 10 8 — it can have at most 8 digits. Hence, the result will be precise if it's in range, and it will not overflow otherwise.


It depends what you use it for. Performing unsigned long(DWORD) addition or Multiplication the best solution is to use ULARGE_INTEGER.

ULARGE_INTEGER is a structure of two DWORDs. The full value can be accessed as "QuadPart" while the hi DWORD is accessed as "HighPart" and the low DWORD is accessed as "LowPart"

उदाहरण के लिए:

DWORD My Addition(DWORD Value_A,DWORD Value_B) { ULARGE_INTEGER a,b;

   b.LowPart = Value_A;  // a 32 bit value(up to 32 bit)
   b.HighPart = 0;
   a.LowPart = Value_B;  // a 32 bit value(up to 32 bit)
   a.HighPart = 0;

   a.QuadPart += b.QuadPart;

   // if  a.HighPart
   // Then a.HighPart contains the overflow(carry)

   return (a.LowPart + a.HighPart)

// any overflow is stored in a.HighPart(up to 32 bits)


The simple way to test for overflow is to do validation by checking whether the current value is less than the previous value. For example, suppose you had a loop to print the powers of 2:

long lng;
int n;
for (n = 0; n < 34; ++n)
{
   lng = pow (2, n);
   printf ("%li\n", lng);
}

Adding overflow checking the way that I described results in this:

long signed lng, lng_prev = 0;
int n;
for (n = 0; n < 34; ++n)
{
    lng = pow (2, n);
    if (lng <= lng_prev)
    {
        printf ("Overflow: %i\n", n);
        /* Do whatever you do in the event of overflow.  */
    }
    printf ("%li\n", lng);
    lng_prev = lng;
}

It works for unsigned values as well as both positive and negative signed values.

Of course, if you wanted to do something similar for decreasing values instead of increasing values, you would flip the <= sign to make it >= , assuming the behaviour of underflow is the same as the behaviour of overflow. In all honesty, that's about as portable as you'll get without access to a CPU's overflow flag (and that would require inline assembly code, making your code non-portable across implementations anyway).


Try this macro to test the overflow bit of 32-bit machines (adapted the solution of Angel Sinigersky)

#define overflowflag(isOverflow){   \
size_t eflags;                      \
asm ("pushfl ;"                     \
     "pop %%eax"                    \
    : "=a" (eflags));               \
isOverflow = (eflags >> 11) & 1;}

I defined it as a macro because otherwise the overflow bit would have been overwritten.

Subsequent is a little application with the code segement above:

#include <cstddef>
#include <stdio.h>
#include <iostream>
#include <conio.h>
#if defined( _MSC_VER )
#include <intrin.h>
#include <oskit/x86>
#endif

using namespace std;

#define detectOverflow(isOverflow){     \
size_t eflags;                      \
asm ("pushfl ;"                     \
    "pop %%eax"                     \
    : "=a" (eflags));               \
isOverflow = (eflags >> 11) & 1;}

int main(int argc, char **argv) {

    bool endTest = false;
    bool isOverflow;

    do {
        cout << "Enter two intergers" << endl;
        int x = 0;
        int y = 0;
        cin.clear();
        cin >> x >> y;
        int z = x * y;
        detectOverflow(isOverflow)
        printf("\nThe result is: %d", z);
        if (!isOverflow) {
            std::cout << ": no overflow occured\n" << std::endl;
        } else {
            std::cout << ": overflow occured\n" << std::endl;
        }

        z = x * x * y;
        detectOverflow(isOverflow)
        printf("\nThe result is: %d", z);
        if (!isOverflow) {
            std::cout << ": no overflow ocurred\n" << std::endl;
        } else {
            std::cout << ": overflow occured\n" << std::endl;
        }

        cout << "Do you want to stop? (Enter \"y\" or \"Y)" << endl;

        char c = 0;

        do {
            c = getchar();
        } while ((c == '\n') && (c != EOF));

        if (c == 'y' || c == 'Y') {
            endTest = true;
        }

        do {
            c = getchar();
        } while ((c != '\n') && (c != EOF));

    } while (!endTest);
}

x86 instruction set includes unsigned multiply instruction that stores the result to two registers. To use that instruction from C one can write following code in 64bit program (gcc):

unsigned long checked_imul(unsigned long a, unsigned long b) {
  __int128 res = (__int128)a * (__int128)b;
  if ((unsigned long)(res >> 64))
    printf("overflow in integer multiply");
  return (unsigned long)res;
}

For 32bit program one needs to make result 64 bit and parameters 32bit.

Alternative is to use compiler depend instincts to check the flag register. GCC documentation for overflow instincts can be found from https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html





integer-overflow