c Printf परिवार का उपयोग कर एक size_t चर पोर्टेबल कैसे मुद्रित कर सकते हैं?




(10)

जैसा कि अरक ने कहा, सी ++ स्ट्रीम इंटरफ़ेस हमेशा पोर्टेबल काम करेगा।

std :: size_t s = 1024; std :: cout << s; // या स्ट्रिंगस्ट्रीम जैसी किसी अन्य प्रकार की स्ट्रीम!

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

सी 99 ने इस समस्या को inttypes.h प्रारूपों के साथ हल करने का प्रयास किया जैसे "%" PRIdMAX "\ n"। लेकिन जैसा कि "% zu" के साथ है, हर कोई c99 का समर्थन नहीं करता है (2013 से पहले एमएसवीएस की तरह)। इस से निपटने के लिए चारों ओर तैरते हुए "msinttypes.h" फ़ाइलें हैं।

यदि आप एक अलग प्रकार के लिए जाते हैं, झंडे के आधार पर आपको छंटनी या संकेत बदलने के लिए एक कंपाइलर चेतावनी मिल सकती है। यदि आप इस मार्ग पर जाते हैं तो एक बड़ा प्रासंगिक निश्चित आकार का प्रकार चुनें। असाइन किए गए लंबे लंबे और "% llu" या हस्ताक्षरित लंबे "% lu" में से एक काम करना चाहिए, लेकिन llu 32 बिट की दुनिया में चीजों को धीमा कर सकता है जितना अधिक बड़ा। (संपादित करें - मेरा मैक 64 बिट में एक चेतावनी जारी करता है जो% llu के आकार से मेल नहीं खाता है, भले ही% lu,% llu, और size_t सभी समान आकार हैं। और% lu और% llu मेरे MSVS2012 पर समान आकार नहीं हैं। आपको + प्रारूपित प्रारूप का उपयोग करने की आवश्यकता हो सकती है।)

उस मामले के लिए, आप int64_t जैसे निश्चित आकार के प्रकारों के साथ जा सकते हैं। लेकिन रुकें! अब हम सी 99 / सी ++ 11 पर वापस आ गए हैं, और पुराने एमएसवीएस फिर से विफल हो जाते हैं। इसके अलावा आप भी रहते हैं (उदाहरण के लिए map.size () एक निश्चित आकार का प्रकार नहीं है)!

आप किसी तृतीय पक्ष शीर्षलेख या लाइब्रेरी जैसे बूस्ट का उपयोग कर सकते हैं। यदि आप पहले से ही एक का उपयोग नहीं कर रहे हैं, तो आप इस तरह अपनी परियोजना को फुला नहीं सकते हैं। यदि आप इस मुद्दे के लिए केवल एक को जोड़ना चाहते हैं, तो सी ++ धाराओं, या सशर्त संकलन का उपयोग क्यों न करें?

तो आप सी ++ धाराओं, सशर्त संकलन, तृतीय पक्ष ढांचे, या आपके लिए काम करने के लिए कुछ प्रकार के पोर्टेबल के लिए नीचे हैं।

मेरे पास size_t प्रकार का एक चर है, और मैं printf() का उपयोग करके इसे प्रिंट करना चाहता हूं। पोर्टेबल प्रिंट करने के लिए मैं किस प्रारूप विनिर्देशक का उपयोग करता हूं?

32-बिट मशीन में, %u सही लगता है। मैं g ++ -g -W -Wall -Werror -ansi -pedantic के साथ संकलित, और कोई चेतावनी नहीं थी। लेकिन जब मैं उस कोड को 64-बिट मशीन में संकलित करता हूं, तो यह चेतावनी उत्पन्न करता है।

size_t x = <something>;
printf( "size = %u\n", x );

warning: format '%u' expects type 'unsigned int', 
    but argument 2 has type 'long unsigned int'

चेतावनी दूर हो जाती है, जैसा कि अपेक्षित है, अगर मैं इसे %lu बदलता हूं।

सवाल यह है कि, मैं कोड कैसे लिख सकता हूं, ताकि यह 32- और 64-बिट मशीनों पर चेतावनी मुक्त हो सके?

संपादित करें: मुझे लगता है कि एक जवाब वैरिएबल को एक unsigned long में "कास्ट" करने और %lu का उपयोग करके मुद्रित करना हो सकता है। यह दोनों मामलों में काम करेगा। मैं देख रहा हूं कि कोई अन्य विचार है या नहीं।


कुछ प्लेटफॉर्म पर और कुछ प्रकार के लिए विशिष्ट प्रिंटफ रूपांतरण विनिर्देशक उपलब्ध होते हैं, लेकिन कभी-कभी किसी को बड़े प्रकार के कास्टिंग का सहारा लेना पड़ता है।

मैंने यहां इस मुश्किल मुद्दे को दस्तावेज किया है, उदाहरण के लिए कोड: http://www.pixelbeat.org/programming/gcc/int_types/ और इसे नए प्लेटफ़ॉर्म और प्रकारों पर जानकारी के साथ समय-समय पर अपडेट करें।


printf("size = %zu\n", sizeof(thing) );

यदि आप एक स्ट्रिंग के रूप में size_t के मान को मुद्रित करना चाहते हैं तो आप यह कर सकते हैं:

char text[] = "Lets go fishing in stead of sitting on our but !!";
size_t line = 2337200120702199116;

/* on windows I64x or I64d others %lld or %llx if it works %zd or %zx */
printf("number: %I64d\n",*(size_t*)&text);
printf("text: %s\n",*(char(*)[])&line);

परिणाम है:

संख्या: 2337200120702199116

पाठ: चलो बैठने के स्थान पर मछली पकड़ने चलो !!

संपादित करें: नीचे दिए गए वोटों के कारण प्रश्न को दोबारा पढ़ना मैंने देखा कि उनकी समस्या% llu या% I64d नहीं है लेकिन विभिन्न मशीनों पर size_t प्रकार इस प्रश्न को देखता है https://.com/a/918909/1755797
http://www.cplusplus.com/reference/cstdio/printf/

size_t 32 बिट मशीन पर हस्ताक्षरित int है और 64 बिट पर बिना लंबे समय तक int unsigned
लेकिन% हमेशा एक हस्ताक्षरित लंबे लंबे int की उम्मीद करेंगे।

size_t विभिन्न ऑपरेटिंग सिस्टम पर लंबाई में भिन्न होता है जबकि% llu समान होता है


विंडोज के लिए एडम रोसेनफील्ड के जवाब पर विस्तार।

मैंने इस कोड का परीक्षण वीएस2013 अपडेट 4 और वीएस2015 पूर्वावलोकन दोनों के साथ किया था:

// test.c

#include <stdio.h>
#include <BaseTsd.h> // see the note below

int main()
{
    size_t x = 1;
    SSIZE_T y = 2;
    printf("%zu\n", x);  // prints as unsigned decimal
    printf("%zx\n", x);  // prints as hex
    printf("%zd\n", y);  // prints as signed decimal
    return 0;
}

वीएस2015 उत्पन्न बाइनरी आउटपुट:

1
1
2

जबकि वीएस2013 द्वारा उत्पन्न एक कहता है:

zu
zx
zd

नोट: ssize_t एक POSIX एक्सटेंशन है और SSIZE_T विंडोज डेटा प्रकारों में समान बात है, इसलिए मैंने <BaseTsd.h> संदर्भ जोड़ा।

इसके अतिरिक्त, सी 99 / सी 11 हेडर का पालन करने के अलावा, सभी सी 99 हेडर वीएस2015 पूर्वावलोकन में उपलब्ध हैं:

C11 - <stdalign.h>
C11 - <stdatomic.h>
C11 - <stdnoreturn.h>
C99 - <tgmath.h>
C11 - <threads.h>

इसके अलावा, सी 11 का <uchar.h> अब नवीनतम पूर्वावलोकन में शामिल है।

अधिक जानकारी के लिए, मानक अनुरूपता के लिए यह old और new सूची देखें।


std::size_t s = 1024;
std::cout << s; // or any other kind of stream like stringstream!

z संशोधक का प्रयोग करें:

size_t x = ...;
ssize_t y = ...;
printf("%zu\n", x);  // prints as unsigned decimal
printf("%zx\n", x);  // prints as hex
printf("%zd\n", y);  // prints as signed decimal

क्या यह आपको चेतावनी देगा यदि आप एक 32-बिट हस्ताक्षरित पूर्णांक को% lu प्रारूप में पास करते हैं? यह ठीक होना चाहिए क्योंकि रूपांतरण अच्छी तरह से परिभाषित है और कोई जानकारी खोना नहीं है।

मैंने सुना है कि कुछ प्लेटफार्म <inttypes.h> में मैक्रोज़ को परिभाषित करते हैं कि आप प्रारूप स्ट्रिंग में <inttypes.h> सकते हैं लेकिन मुझे अपने विंडोज सी ++ कंपाइलर पर हेडर नहीं दिख रहा है, जिसका अर्थ है कि यह क्रॉस-प्लेटफॉर्म नहीं हो सकता है।


सी 99 इसके लिए "% zd" इत्यादि परिभाषित करता है। (टिप्पणीकारों के लिए धन्यवाद) सी ++ में इसके लिए कोई पोर्टेबल प्रारूप विनिर्देशक नहीं है - आप %p उपयोग कर सकते हैं, जो इन दो परिदृश्यों में शब्द woulkd है, लेकिन यह एक पोर्टेबल विकल्प नहीं है, और हेक्स में मान देता है।

वैकल्पिक रूप से, कुछ स्ट्रीमिंग (जैसे स्ट्रिंगस्ट्रीम) या बूस्ट प्रारूप जैसे सुरक्षित प्रिंटफ प्रतिस्थापन का उपयोग करें। मैं समझता हूं कि यह सलाह केवल सीमित उपयोग है (और सी ++ की आवश्यकता है)। (यूनिकोड समर्थन को कार्यान्वित करते समय हमने अपनी जरूरतों के लिए एक समान दृष्टिकोण का उपयोग किया है।)

सी के लिए मौलिक समस्या यह है कि एक इलिप्सिस का उपयोग कर प्रिंटफ डिज़ाइन द्वारा असुरक्षित है - इसे ज्ञात तर्कों से अतिरिक्त तर्क के आकार को निर्धारित करने की आवश्यकता है, इसलिए इसे "जो भी मिला है" का समर्थन करने के लिए इसे ठीक नहीं किया जा सकता है। इसलिए जब तक आपका कंपाइलर कुछ मालिकाना एक्सटेंशन लागू नहीं करता है, तो आप भाग्य से बाहर हैं।


ऐसा लगता है कि आप किस कंपाइलर का उपयोग कर रहे हैं (ब्लीच) के आधार पर भिन्न होता है:

... और निश्चित रूप से, यदि आप सी ++ का उपयोग कर रहे हैं, तो आप अराक द्वारा सुझाए गए अनुसार कॉउट का उपयोग कर सकते हैं।





printf