2012-10-21 15 views
7

मेरे प्रश्न एकाधिक बिट-गहराई प्लेटफॉर्म (उदाहरण के लिए 32/64) के निर्माण के लिए प्रयास करते समय चीजों को लॉग करने के लिए printf का उपयोग करने का प्रयास करने से रोकते हैं।क्या printf तर्कों में प्रकारों को बढ़ावा देना खतरनाक है?

एक समस्या जो उसके बदसूरत सिर को बरकरार रखती है वह कई आर्किटेक्चर पर इन्ट्स प्रिंट करने की कोशिश कर रही है। 32 बिट पर यह

printf(" my int: %d\n", myInt); 

की तरह कुछ होगा, लेकिन 64 बिट पर है, यह मैं दो संबंधित प्रश्न पूछना चाहते हैं

print (" my int: %ld\n", (long)myInt); 

के लिए बदला जा करने के लिए होगा:

  1. मेरी पहली सोचा यह था कि जब आप एक चर को मुद्रित करने के लिए printf को बताते हैं, तो इसे एक प्रारूप देते हुए, यह उस चर के पते को देखेगा और उस प्रारूप के लिए आवश्यक कई बाइट्स को पकड़ लेगा। यह पहली बार एक बड़ी समस्या की तरह लग रहा था। उदाहरण के लिए यदि आपके पास एक वैरिएबल MyChar था जो एक char (1 बाइट) था, लेकिन% d के प्रारूप विनिर्देशक का उपयोग करता था, जो प्रिंटफ को myChar के पते पर जाने के लिए बताएगा और अगले 4 बाइट्स को एक int की तरह व्यवहार करने के लिए पकड़ लेगा। यदि ऐसा होता है, तो ऐसा लगता है कि printf पड़ोसी चर से कचरा तिथि ले जाएगा (क्योंकि यह 4 बाइट पकड़ रहा था, लेकिन वास्तविक मूल्य केवल 1 बाइट है)। हालांकि यह मामला नहीं है। MyChar का उपयोग करके और% d निर्दिष्ट करके, printf 1 बाइट grabs और फिर ऊपरी 3 बाइट 0 के साथ पैड। क्या मेरी समझ यहां सही है?

  2. यदि उपर्युक्त सत्य है, तो 32/64 बिट मामले में देखी गई समस्याओं के प्रकार से बचने के लिए हमेशा अपने सबसे बड़े मूल्यों तक चर को बढ़ावा देने में कोई वास्तविक नुकसान होता है। उदाहरण के लिए यदि आपके पास एक छोटा चर MyShort है, और एक int variable, myInt, उन्हें हमेशा प्रिंट करने में कोई नकारात्मकता है:

    printf ("myShort% ld", (long) myShort); printf ("myInt% ld", (लंबा) myInt);

किसी भी स्पष्टीकरण के लिए धन्यवाद।

+0

[वैरैडिक फ़ंक्शन में स्वचालित प्रकार का प्रचार] का संभावित डुप्लिकेट (http://stackoverflow.com/questions/7084857/automatic-type-promotion-in-variadic- कार्यक्षमता) –

+1

आईएमओ, वास्तव में डुप्लिकेट के नजदीक नहीं । मैं लोगों को बंद करने के बजाए यहां चर्चा जारी रखने के लिए प्रोत्साहित करता हूं। –

+3

आप क्यों मानते हैं कि 'printf ("% d", myInt);' 64-बिट प्लेटफार्मों के लिए बदला जाना है? –

उत्तर

6

printf के संबंध में: यदि आप बैठे हैं, तो "% d" विनिर्देश के अनुसार, प्लेटफ़ॉर्म-परिभाषित 'int' डेटा प्रकार को संभालना चाहिए। इससे कोई फर्क नहीं पड़ता कि यह 32 बिट्स, 64 बिट्स, या 128 बिट रैखिक एएस/400 मूल्य है। आप एक बड़ा क्षेत्र प्रकार के लिए मूल्य को बढ़ावा देने के (और संबंधित प्रारूप स्ट्रिंग कण के साथ कि पदोन्नति से मेल खाते हैं) चाहते हैं आप निश्चित रूप से ऐसा करने के लिए स्वतंत्र हैं,

int a=0; 
printf("%ld", (long)a); 

निश्चित रूप से बढ़ावा देने का उपयोग कर व्यवहार परिभाषित किया गया है।

मुझे लगता है कि आपके प्रश्न का वास्तविक क्रूक्स निम्नलिखित मामलों में आता है, और क्या पदोन्नति को मजबूर करना किसी भी समस्या का समाधान "हल" कर सकता है।

char ch = 'a'; 
printf("%d", ch); 

या के बारे में क्या: उदाहरण के लिए:

char ch = 'a'; 
printf("%ld", (long)ch); 

या हो सकता है यह (आप से बचने की कोशिश कर रहे हैं जो वास्तविक स्थिति है):

char ch = 'a'; 
printf("%ld", ch); 

इनमें से पहला काम करेगा, लेकिन केवल इसलिए कि वीए-एआरआर सूची पर स्टैक-पुश किए गए किसी भी प्रकार का न्यूनतम आकार int का प्लेटफ़ॉर्म आकार है। संकलक आपके लिए एक int को मूल्य को स्वत: प्रचारित करेगा। चूंकि "% d" अपेक्षा करता है कि प्लेटफ़ॉर्म int सभी ठीक दिखाई देंगे।

दूसरा हमेशा काम करेगा और पूरी तरह से समर्थित है। char से long पर एक स्पष्ट और परिभाषित प्रचार है। भले ही long 64 बिट (या बड़ा) है, फिर भी यह काम करेगा।

तीसरा यूबी सभी तरह से है। printflong की तलाश में है और इसे int के लिए केवल बाइट्स के साथ प्रस्तुत किया जाएगा। यदि यह आपके प्लेटफ़ॉर्म पर "काम" लगता है, तो int और long के लिए अपनी प्लेटफ़ॉर्म चौड़ाई जांचें। यह संभवतः "कामकाजी" होने की संभावना है क्योंकि आपका प्लेटफ़ॉर्म long और int समान बिट-चौड़ाई है। प्लेटफॉर्म पर कोड को पोर्ट करते समय मजेदार आश्चर्य की बात होती है, और जब से इसे वीए-एर्ग के माध्यम से धक्का दिया जाता है, तब तक आप इसे वास्तविक तक नहीं देख पाएंगे, अलग-अलग चौड़ाई खेलने के लिए आती हैं।

कि सब के सब कहा जा रहा है, अब ऐसा है कि scanf के लिए आवश्यक है और हम कुछ पूरी तरह से अलग पर देख रहे हैं के रूप में (कुछ भी वास्तव में) कुछ करने के लिए एक वास्तविक पता फेंक देते हैं।

int val; 
sscanf("%ld",&val); 

यह एक सीजी-गलती होने का इंतजार कर रहा है। उपर्युक्त की तरह, आप इसे कभी नहीं जानते होंगे यदि आपका प्लेटफ़ॉर्म long और प्लेटफ़ॉर्म int समान चौड़ाई है। इस कोड को एक बॉक्स में ले जाएं जहां long और int अलग-अलग आकार हैं और आगामी कोर फ़ाइल के जीडीबी लोड के लिए स्वयं को तैयार करें।

0

bools/_Bools, chars और shorts पहले int में बदला जाता है (इस रूपांतरण unsigned int में मूल्य को बरकरार रखता है, और अगर) जब printf() तरह variadic कार्यों के लिए पारित कर दिया। इसी तरह floatsdoubles में परिवर्तित हो गया है।

तो, अगर आप कुछ int की तुलना में छोटे गुजरती हैं, printf() बिना किसी समस्या के पूरे (unsigned) int (यदि भेजे गए मान को वास्तव में एक unsigned int है के अलावा अन्य हड़पने जाएगा और आप %d बजाय %u साथ यह प्रिंट कर रहे हैं, तो आप अपरिभाषित व्यवहार मिलता है)।

अन्य प्रकार, AFAIR, ऐसे रूपांतरण नहीं करते हैं।

यह पंक्ति:

print (" my int: %ld\n", (long)myInt); 

इस लाइन पर आप कुछ भी खरीद नहीं है:

printf(" my int: %d\n", myInt); 

दोनों मान्य हैं और परिणाम व्यावहारिक रूप से समान होगा। केवल अंतर यह है कि पूर्व के परिणामस्वरूप बड़ा कोड और अधिक निष्पादन समय हो सकता है (यदि sizeof(long) >= sizeof(int))।

0
  1. तर्क स्टैक में पारित किए जाते हैं, जिसमें प्रत्येक प्रविष्टि की निश्चित चौड़ाई (32 या 64) बिट्स होती है। कंपाइलर आर्किटेक्चर की मूल चौड़ाई में या 32 आर्किटेक्चर पर डबल (या लंबे लंबे) के मामले में पूर्णांक, वर्ण, शॉर्ट्स को 'कास्ट करता है', यह ढेर से दो स्लॉट आवंटित करता है। "पैडिंग" या तो शून्य के साथ किया जाता है, या चर के बिट बिट को शेष बिट्स पर कॉपी किया जाता है। (साइन बिट एक्सटेंशन कहा जाता है)

  2. 64 बिट्स को बढ़ावा देने में एक नकारात्मक पक्ष एम्बेडेड सिस्टम में संगतता की कमी है, जो अक्सर 64-बिट प्रिंटिंग प्रदान नहीं करता है। इसके अलावा इसका मतलब 32-बिट सिस्टम में कुछ प्रदर्शन जुर्माना है क्योंकि शीर्ष 32-बिट हमेशा पारित होते हैं और परिवर्तित होते हैं (इसमें 10 बिट द्वारा 64 बिट चौड़ा विभाजन होता है) बिना किसी वास्तविक उपयोग के। हालांकि बड़ी समस्या सॉफ्टवेयर इंजीनियरिंग के डोमेन में आती है: क्या "भविष्य संगत" लॉग एक झूठी आशा देता है कि सिस्टम की सभी गणना और 32-बिट सिस्टम पर 64-बिट मोड में सिस्टम के सभी इनपुट भी काम करते हैं।

(लंबे) 32-बिट आर्किटेक्चर में 64 बिट का मतलब नहीं है। यह (लंबे समय तक) के साथ नोट किया गया है।

1

तुमने कहा था:

एक समस्या यह है कि अपनी बदसूरत सिर उठा रहता है कई आर्किटेक्चर पर ints मुद्रित करने के लिए

यह कोशिश करते हैं और में पास करके प्रकार के मुद्दों के सामने लाने के लिए खतरनाक है कोशिश कर रहा है वे मान जो उस प्रकार के आकार के नहीं हैं, हां। Thats क्यों संकलक आपको चेतावनी देता है। पोर्टेबिलिटी की धारणा जो आपको समस्याएं पैदा कर रही है, प्रिंटफ को खुश करने के लिए डिज़ाइन नहीं की गई है।

यह आपके प्रोग्राम को चलाने और कई आर्किटेक्चर पर क्रैश नहीं करने के लिए डिज़ाइन किया गया है। यदि आपके पास प्लेटफॉर्म विशिष्ट कोड है तो आपको इसके आसपास काम करने के लिए #ifdef मैक्रोज़ का उपयोग करना चाहिए।

अन्यथा आप मेमोरी स्तर प्रकार रूपांतरण पर परत लगाने की कोशिश कर पासा रोलिंग कर रहे हैं।

printf एक सुविधा प्रकार प्रकार रूपांतरण पद्धति नहीं है।

ऐसा लगता है कि आप इनट्स पर केंद्रित हैं - जो आप शायद दूर हो जाएंगे। लेकिन आम तौर पर मैं इस तरह की तकनीक पर भरोसा नहीं करता।

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