सी

2012-01-19 5 views
5

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

#include <stdio.h> 
#include <stdint.h> 

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

    uint32_t foo = -1; 
    uint32_t u = 2048; 
    uint64_t ul = 2048; 

    fprintf(stderr, "%d\n", foo); 
    fprintf(stderr, "%u\n", foo); 
    fprintf(stderr, "%lu\n", ((foo * 2600000000) % u)); 
    fprintf(stderr, "%ld\n", ((foo * 2600000000) % u)); 
    fprintf(stderr, "%lu\n", ((foo * 2600000000) % ul)); 
    fprintf(stderr, "%lu\n", foo % ul); 

    return 0; 

} 

इस, निम्नलिखित उत्पादन का उत्पादन मेरी x86_64 मशीन पर: यहाँ एक उदाहरण कार्यक्रम प्रदर्शित करने के लिए है

-1 
4294967295 
18446744073709551104 
-512 
1536 
2047 

1536 नंबर मैं उम्मीद कर रहा था है, लेकिन (uint32_t) (- 512) है जिस नंबर को मैं प्राप्त कर रहा था, जिसे आप कल्पना कर सकते हैं, चीजों को थोड़ा सा फेंक दिया।

तो, मुझे लगता है कि मेरा प्रश्न यह है: इस मामले में दो हस्ताक्षरित संख्याओं के बीच एक मॉड्यूलस ऑपरेशन, एक संख्या का उत्पादन करता है जो विभाजक (यानी ऋणात्मक संख्या) से अधिक है? क्या इस व्यवहार को प्राथमिकता दी गई है?

+1

2600000000 एक int (या शायद 64-बिट int-long या long long) है, जो गुणा के परिणाम को (हस्ताक्षरित) लंबा होने का परिणाम हो सकता है। आप किस मंच पर हैं? – Random832

उत्तर

3

मुझे लगता है कि कारण यह है कि संकलक, एक हस्ताक्षरित 64-बिट संख्या के रूप में 2600000000 शाब्दिक व्याख्या करने के तरीके के बाद से यह एक हस्ताक्षरित 32-बिट पूर्णांक में फिट नहीं बैठता है की कोशिश करो। यदि आप 2600000000U के साथ नंबर को प्रतिस्थापित करते हैं, तो आपको परिणाम प्राप्त करना चाहिए।

+2

असल में ओपी ने 'printf' को गलत प्रारूप तारों को पार करके यूबी को बुलाया। –

2

मेरे पास कोई संदर्भ आसान नहीं है, लेकिन मुझे यह सुनिश्चित है कि जब आप उस गुणा को करते हैं, तो यह उन्हें int64_t पर बढ़ावा देता है, क्योंकि इसे दो गुणांक को एक हस्ताक्षरित अभिन्न प्रकार पर मजबूर करने की आवश्यकता होती है। 2600000000u बजाय 2600000000 ....