2017-06-07 57 views
8

में variadic मापदंडों एक चर तर्क समारोह ग पूर्णांक मानकों में कहा जाता है जब की बेहतर समझ के प्रकार को बढ़ावा देने के लिए int करने के लिए प्रोत्साहित कर रहे हैं और चल बिन्दु मापदंडों

दोगुना करने के बाद से प्रोटोटाइप प्रकार निर्दिष्ट नहीं करता प्रचारित किया जाता है वैकल्पिक तर्कों के लिए, एक भिन्न कार्य के लिए कॉल में डिफ़ॉल्ट तर्क प्रचार वैकल्पिक तर्क मानों पर किया जाता है। इसका अर्थ है char या short int (चाहे हस्ताक्षरित या नहीं) की वस्तुओं को उचित रूप से int या unsigned int पर प्रचारित किया गया हो; और float प्रकार की वस्तुओं को double टाइप करने के लिए प्रचारित किया जाता है। इसलिए, यदि कॉलर char को वैकल्पिक तर्क के रूप में पास करता है, तो इसे int पर प्रचारित किया जाता है, और फ़ंक्शन va_arg (ap, int) के साथ इसका उपयोग कर सकता है।

int प्रकार 64 बिट मशीनों पर 4 बाइट और 64 बिट मशीनों पर 8 बाइट होना चाहिए, क्या यह सही है?
तो मुझे आश्चर्य है कि जब मैं को %lld प्रारूप के साथ printf जैसे एक चर तर्क तर्क फ़ंक्शन पर पास करता हूं तो क्या जोड़ता है।
और फिर, मुझे आश्चर्य है कि जब मैं long double को %Lf प्रारूप के साथ printf (32 या 64 बिट मशीनों पर कोई फर्क नहीं पड़ता) के साथ printf को पास करता हूं तो मुझे क्या आश्चर्य होता है।

#include <stdio.h> 

int main(void) 
{ 
    printf("sizeof(int) %d\n", sizeof(int)); 
    printf("sizeof(long int) %d\n", sizeof(long int)); 
    printf("sizeof(long long int) %d\n", sizeof(long long int)); 
    printf("%lld\n", 1LL<<33); 

    printf("sizeof(float) %d\n", sizeof(float)); 
    printf("sizeof(double) %d\n", sizeof(double)); 
    printf("sizeof(long double) %d\n", sizeof(long double)); 
    return 0; 
} 

परिणाम है::

sizeof(int) 4 
sizeof(long int) 4 
sizeof(long long int) 8 
8589934592 
sizeof(float) 4 
sizeof(double) 8 
sizeof(long double) 12 

यह मेरे लगता है कि नहीं सभी मापदंडों हैं बनाता है

[संपादित]

एक 32 बिट मशीन पर

, मैं इस कोशिश की int को पदोन्नत किया गया, अन्यथा मुझे 858 9934592 के बजाय 0 मुद्रित किया जाएगा।

शायद int से कम केवल तर्क int पर प्रचारित हैं। और कुछ ऐसा ही फ़्लोटिंग पॉइंट प्रकारों के लिए हो सकता है।

[संपादित]

एक 64 बिट मशीन पर

मैं चलाने इस:

int main(void) 
{ 
    printf("sizeof(int) %lu\n", sizeof(int)); 
    printf("sizeof(long) %lu\n", sizeof(long)); 
    printf("sizeof(long long) %lu\n", sizeof(long long)); 
    return 0; 
} 

और

sizeof(int) 4 
sizeof(long) 8 
sizeof(long long) 8 

मिल अगर मैं अच्छी तरह से मानक को समझते हैं, केवल char और short हैं int को पदोन्नत किया गया। मुझे आश्चर्य है कि छोटे आर्किटेक्चर में क्या होता है, जैसे कि 16 बिट या 8 बिट एमसीयू। मुझे लगता है कि int आकार आर्किटेक्चर द्वारा निर्भर है, लेकिन मुझे आश्चर्य है कि sizeof(int) 8 बिट आर्किटेक्चर पर 1 हो सकता है। shortint के इस मामले को बढ़ावा देने में असंभव है जब तक कि कुछ बिट्स

+2

'int' _at कम से कम 16 बिट्स होना चाहिए, लेकिन मानक द्वारा कोई और गारंटी नहीं दी जाती है। –

+1

और 'लंबा लंबा' कम से कम 64 बिट प्रति सी 99 – 4386427

+0

होना चाहिए [एक 'int'' छोटा 'होना शामिल होना चाहिए (http://port70.net/~nsz/c/c11/n1570.html# 6.2.5p8)। साथ ही, मानक निर्दिष्ट करता है कि अंतर्निहित वास्तुकला के बावजूद एक ['int 'कम से कम 16 बिट्स होना चाहिए) (http://port70.net/~nsz/c/c11/n1570.html#5.2.4.2.1)। '_Bool' को 'int' में भी बढ़ावा दिया जाता है। –

उत्तर

7

"int प्रकार 64 बिट मशीनों पर 4 बाइट और 64 बिट मशीनों पर 8 बाइट होना चाहिए, क्या यह सही है?" नहीं। मानक के अनुसार, ints must be at least 16 bits in width (§5.2.4.2.1), लेकिन कोई और शर्त नहीं है।

जब आप पारित एक long long intprintf() करने के लिए इसे नहीं विषय the integer promotions (§6.3.1.1 2) के लिए है:

निम्नलिखित एक अभिव्यक्ति में इस्तेमाल किया जा सकता जहाँ भी किसी पूर्णांक या अहस्ताक्षरित पूर्णांक में इस्तेमाल किया जा सकता है:

  • एक ऑब्जेक्ट या अभिव्यक्ति एक पूर्णांक प्रकार (int या unsigned int के अलावा) जिसका पूर्णांक रूपांतरण रैंक से कम या उसके बराबर int और unsigned int के बराबर है।
  • प्रकार का थोड़ा-क्षेत्र _Bool, int, हस्ताक्षरित int, या हस्ताक्षरित int।

किसी पूर्णांक मूल प्रकार (, चौड़ाई से प्रतिबंधित के रूप में थोड़ा-क्षेत्र के लिए) के सभी मूल्यों का प्रतिनिधित्व कर सकते हैं, मूल्य एक पूर्णांक में बदल जाती है; अन्यथा, इसे एक हस्ताक्षरित int में परिवर्तित कर दिया जाता है। इन्हें पूर्णांक पदोन्नति.58 कहा जाता है) अन्य सभी प्रकार पूर्णांक प्रचार द्वारा अपरिवर्तित हैं।

आप पार कर लेते हैं एक long doubleprintf() को no conversion is made (§6.5.2.2 6):

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

printf() बयान में बहस करने के लिए इसी रूपांतरण विनिर्देशक को छोड़कर जहां तक ​​वहाँ अपरिभाषित व्यवहार करता है, तो विनिर्देशक कर उनके संबंधित तर्क के प्रकार से मेल नहीं खाते हो जाएगा, ये प्रचार और रूपांतरण से कोई संबंध नहीं है।

तो, पूर्णांक प्रचार प्रदर्शन किए जाते हैं, और float एस double एस में परिवर्तित हो जाते हैं, लेकिन "No other conversions are performed implicitly" (§6.5.2.2 8)

प्रश्न में आपके संपादन को संबोधित करते हुए: "इससे मुझे लगता है कि सभी पैरामीटर int पर प्रचारित नहीं हैं।" सही बात। पूर्णांक रूपांतरण रैंक वाले केवल पूर्णांक प्रकार "int और unsigned int के रैंक से कम या उसके बराबर" पूर्णांक पदोन्नति के अधीन हैं। फ्लोटिंग पॉइंट प्रकारों के लिए यह आसान है; float एस को double पर पदोन्नत किया जाता है। बस इतना ही।

यह उनका कहना है कि, §6.2.5 10 के अनुसार, वहाँ तीन असली फ्लोटिंग बिंदु प्रकार, float, double, और long double हैं लायक हो सकता है। float द्वारा रखे जाने वाले मान double द्वारा रखे गए मानों का सबसेट हैं, जो बदले में long double द्वारा रखे गए मानों का एक सबसेट है। इसलिए, long double प्रकारों के लिए पदोन्नति की कोई संभावना नहीं है।

इसके अलावा, §6.3.1.1 1 के अनुसार:

लंबे पूर्णांक के पद लंबे पूर्णांक के पद, जो पूर्णांक के पद से भी बड़ा होगा, जो अधिक से अधिक से किया जाएगा की तुलना में अधिक हो जाएगा लघु int का रैंक, जो हस्ताक्षर चार के रैंक से अधिक होगा।

तो वहाँ एक long long int या long int कभी int या unsigned int करने के लिए प्रोत्साहित किया जा रहा की कोई संभावना नहीं है।

अपने अंतिम चिंता यह है कि एक int करने के लिए एक short को बढ़ावा देना, कुछ कार्यान्वयन में, असंभव कुछ बिट्स खोने के बिना हो सकता है, ध्यान दें कि §6.2.5 8 गारंटी देता है कि एक int, एक short शामिल करने के लिए सक्षम होना चाहिए के रूपांतरण रैंक के बाद के रूप में एक int की तुलना में अधिक होना चाहिए एक short:

ही signedness और विभिन्न पूर्णांक रूपांतरण रैंक (6.3.1.1 देखें), छोटे पूर्णांक के साथ प्रकार के मानों की श्रेणी के साथ किसी भी दो पूर्णांक प्रकार के लिए रूपांतरण रैंक एक subrange है के मूल्यों के अन्य प्रकार के।

+0

मैं केवल उदाहरण के लिए printf के बारे में बात करता हूं। मुझे आश्चर्य है, अगर मैं अपना वैरिडिक फ़ंक्शन लिखता हूं, तो मैं इसे पास करता हूं, सभी को int या केवल छोटे में परिवर्तित कर दिया जाता है? मैंने – mastupristi

+0

@ मास्टुप्रिस्टी को समझाए जाने के लिए मूल पोस्ट संपादित किया - पदोन्नति के नियम किसी भी विविध कार्य के लिए समान हैं। –

+0

@ डेविड - फ्लोटिंग पॉइंट प्रकारों के लिए समान होना चाहिए: 'फ्लोट' को 'डबल' तक प्रचारित किया जाता है, और 'लंबे डबल' के लिए कोई रूपांतरण नहीं होता है। मैंने कुछ अन्य सामान – mastupristi

1

तो मुझे आश्चर्य है कि क्या संलग्न खो जब मैं %lld प्रारूप साथ printf की तरह एक चर तर्क कार्य करने के लिए एक long long int पारित हो सकता है।और, फिर, मुझे आश्चर्य है कि क्या है जब मैं long double वैरिएबल को %Lf प्रारूप (32 या 64 बिट मशीनों पर कोई फर्क नहीं पड़ता) के साथ printf को पास करता है।

कुछ भी नहीं है, के रूप में होता है long long intint के रूप में एक ही आकार के कम से कम हो गया है। यहां तक ​​कि सबसे अधिक "पेसिमिस्टिक" परिदृश्य में, जहां sizeof(long long int) == sizeof(int), तर्क अभी भी "जैसा है" (बिना किसी प्रचार के) पारित किया गया है। यह long double पर लागू होता है।

3

पूर्णांक प्रकार 32 बिट मशीनों पर 4 बाइट और 64 बिट मशीनों पर 8 बाइट होना चाहिए, यह सही है?

शायद नहीं। सबसे पहले, सी int के आकार के बारे में कोई गारंटी नहीं देता है, यह बताते हुए कि कम से कम 2 बाइट्स (कम से कम मूल्य 2^16/2 - 1 = 32767) रखने में सक्षम होना चाहिए। सी में कुछ भी 0 बाइट्स होने से int को रोकता है, लेकिन यह बहुत सुविधाजनक नहीं है।

सम्मेलन है: सभी 8- और 16 बिट कंप्यूटर 16 बिट int का उपयोग करते हैं। अन्य सभी कंप्यूटर 32 बिट int का उपयोग करते हैं। यह उद्योग वास्तव में मानक है। इस सम्मेलन से कोई विचलन, बहुत विदेशी होगा हालांकि सिद्धांत रूप में सी


द्वारा अनुमति तो मुझे आश्चर्य है कि क्या संलग्न जब मैं एक लंबे% lld प्रारूप साथ printf की तरह एक चर तर्क कार्य करने के लिए पूर्णांक गुजरती हैं।

आपको एक लंबा लंबा int मिलता है। कोई पदोन्नति नहीं होती है, क्योंकि चर निर्दिष्ट छोटे प्रकारों में से एक नहीं है। प्रयुक्त प्रारूप विनिर्देश पदोन्नति नियमों के लिए अप्रासंगिक है।


यह मेरे लगता है कि नहीं सभी मापदंडों दरअसल

int करने के लिए प्रोत्साहित किया जाता है बनाता है। केवल मानक प्रकारों का प्रचार किया जाता है। डिफ़ॉल्ट तर्क प्रोन्नति की औपचारिक परिभाषा C11 6.5.2.2/6 में पाया जा सकता:

... पूर्णांक प्रोन्नति प्रत्येक तर्क पर प्रदर्शन कर रहे हैं, और तर्क है कि प्रकार नाव को दोगुना करने के लिए प्रोत्साहित कर रहे हैं। ये को डिफ़ॉल्ट तर्क प्रचार कहा जाता है।

मतलब यह है कि केवल छोटे पूर्णांक प्रकार (पूर्णांक पदोन्नति नियम देखें) और float को बढ़ावा दिया जाता है। कोई अन्य प्रकार नहीं।


तुम्हें क्या लगता है कि अपने उदाहरण विभिन्न प्रकार आकार मुद्रण डिफ़ॉल्ट तर्क पदोन्नति के संबंध में कोई प्रासंगिकता है, मुझे पता नहीं है।

+0

यूवी "प्रारूप विनिर्देशक प्रचार पदों के लिए अप्रासंगिक है।" – chux