2009-09-06 19 views
10

ले लो निम्नलिखित:सी: मुद्रण बड़ी संख्या

Without variable : 18035667472744448 
With variable : 285212672 

आप ऊपर से देख सकते हैं, printf पारित हो जाता है जब:

#include <stdio.h> 

main() { 
    unsigned long long verybig = 285212672; 

    printf("Without variable : %llu\n", 285212672); 
    printf("With variable : %llu", verybig); 
} 

यह उपरोक्त कार्यक्रम के उत्पादन में है स्थिर संख्या के रूप में, यह कुछ विशाल गलत संख्या प्रिंट करता है, लेकिन जब मान को पहले चर में संग्रहीत किया जाता है, printf सही संख्या प्रिंट करता है।

इसके पीछे तर्क क्या है?

उत्तर

25

285212672ULL आज़माएं; यदि आप इसे प्रत्यय के बिना लिखते हैं, तो आप पाएंगे कि संकलक इसे नियमित पूर्णांक के रूप में मानता है। एक चर में काम करने का कारण यह है कि पूर्णांक को unsigned long long पर असाइनमेंट में डाला जा रहा है, ताकि printf() पर दिया गया मान सही प्रकार का हो।

और इससे पहले कि आप से पूछना, नहीं, संकलक शायद नहीं बहुत चालाक printf() प्रारूप स्ट्रिंग में "%llu "से यह पता लगाने की है। यही कारण है कि अमूर्त का एक अलग स्तर है। संकलक भाषा वाक्य रचना के लिए जिम्मेदार है , printf() अर्थ विज्ञान वाक्य रचना का हिस्सा नहीं हैं, यह एक क्रम पुस्तकालय समारोह (अपने खुद के कार्यों से वास्तव में अलग नहीं सिवाय इसके कि यह मानक में शामिल है)

एक 32-बिट पूर्णांक और 64 के लिए निम्न कोड पर विचार करें है। -बिट हस्ताक्षरित लंबी लंबी प्रणाली:

#include <stdio.h> 

int main (void) { 
    printf ("%llu\n",1,2); 
    printf ("%llu\n",1ULL,2); 
    return 0; 
} 

जो आउटपुट:

8589934593 
1 

पहले मामले में, दो 32-बिट पूर्णांक 1 और 2 ढेर पर धकेल दिया जाता है और printf() समझता है कि वह एक भी 64-बिट ULL मूल्य के रूप में, 2 एक्स 2 + 1. 2 तर्क अनजाने में यूएलएल मूल्य में शामिल किया जा रहा है।

दूसरे में, आप वास्तव में 64-बिट 1-मान और एक अनावश्यक 32-बिट पूर्णांक 2 दबाते हैं, जिसे अनदेखा किया जाता है।

ध्यान दें कि यह आपके प्रारूप स्ट्रिंग और आपके वास्तविक तर्कों के बीच "चरण से बाहर निकलना" एक बुरा विचार है। की तरह कुछ:

printf ("%llu %s %d\n", 0, "hello", 0); 

दुर्घटना क्योंकि 32-बिट "hello" सूचक %llu और %s द्वारा भस्म हो जाएगा-संदर्भ डी के लिए अंतिम 0 तर्क की कोशिश करेंगे की संभावना है। निम्नलिखित "चित्र" यह दिखाता है (मान लीजिए कि कोशिकाएं 32-बिट हैं और "हैलो" स्ट्रिंग 0xbf000000 पर संग्रहीत है।

What you pass  Stack frames  What printf() uses 
       +------------+ 
0    | 0   | \ 
       +------------+ > 64-bit value for %llu. 
"hello"   | 0xbf000000 |/
       +------------+ 
0    | 0   | value for %s (likely core dump here). 
       +------------+ 
       | ?   | value for %d (could be anything). 
       +------------+ 
+1

लेकिन मुझे लगता है कि संकलक बहुत चालाक में यू% यह पता लगाने की है printf प्रारूप spec, printf ("% d% u", ~ 0, ~ 0) का प्रयास करें .. दोनों मूल्यों को अपेक्षित रूप से प्रिंट करेंगे .. – sud03r

+0

नहीं - वे डेटा प्रकार एक ही आकार के हैं - यह printf() यह पता लगाने की कोशिश कर रहा है - कोशिश करें 'डी' के साथ% d। – paxdiablo

+0

पैक्स: यह भी ठीक है, चरित्र अक्षर पूर्णांक स्थिरांक हैं। – caf

3

285212672 एक int मूल्य है। printfunsigned long long की अपेक्षा करता है और आप इसे int पास कर रहे हैं। नतीजतन, यह वास्तविक मूल्य पारित करने और कचरे को मुद्रित करने से अधिक ढेर से अधिक बाइट ले जाएगा। जब आप इसे फ़ंक्शन में पास करने से पहले unsigned long long वैरिएबल में डालते हैं, तो इसे असाइनमेंट लाइन में unsigned long long पर प्रचारित किया जाएगा और आप उस मान को printf पर भेज देंगे जो सही तरीके से काम करता है।

0

डाटाटाइप बस एक स्मृति स्थान की सामग्री की व्याख्या का एक तरीका है।
पहले मामले में निरंतर मान को केवल एक स्मृति के रूप में पढ़ने के लिए स्मृति स्थान में संग्रहीत किया जाता है, printf इस पते को 8 बाइट स्थान के रूप में समझने की कोशिश करता है क्योंकि यह निर्देश दिया जाता है कि संग्रहीत मूल्य लंबे समय तक कचरा मूल्य प्रिंट करता है।
दूसरे मामले में printf एक लंबे लंबे मान को 8 बाइट्स के रूप में समझने की कोशिश करता है और यह अपेक्षा करता है कि यह क्या अपेक्षा करता है। -

5

यह उनका कहना है कि कुछ compilers इस मामले के लिए एक उपयोगी चेतावनी दे लायक है उदाहरण के लिए, इस जीसीसी अपने कोड के बारे में क्या कहते हैं:

x.c: In function ‘main’: 
x.c:6: warning: format ‘%llu’ expects type ‘long long unsigned int’, but argument 2 has type ‘int’ 
+1

फिर भी एक और कारण संकलन * चेतावनी * को अनदेखा नहीं करना है। – reuben

संबंधित मुद्दे