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


403

मेरे पास एक प्रकार का चर है 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। यह दोनों मामलों में काम करेगा। मैं देख रहा हूं कि क्या कोई अन्य विचार है।


4
unsigned longयदि आपका एफबीआईसी कार्यान्वयन zसंशोधक का समर्थन नहीं करता है तो कास्टिंग सबसे अच्छा विकल्प है ; C99 मानक size_tएक पूर्णांक रूपांतरण रैंक की तुलना में अधिक नहीं होने की सलाह देता है long, इसलिए आप यथोचित रूप से सुरक्षित हैं
Christoph



1
विंडोज प्लेटफॉर्म पर size_t लंबे समय से बड़ा हो सकता है। संगतता कारणों के लिए हमेशा 32-बिट होता है, लेकिन size_t 64-बिट हो सकता है। तो, अहस्ताक्षरित लंबे समय तक कास्टिंग करने से बिट्स का आधा हिस्सा खो सकता है। क्षमा करें :-)
ब्रूस डॉसन

जवाबों:


481

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

7
+1। क्या यह C99 जोड़ है या यह C ++ पर भी लागू होता है (मेरे पास C90 काम नहीं है)?
अवकर

6
यह printf()2009-11-09 (पृष्ठ 672 पर तालिका 84) से C ++ 0x ड्राफ्ट की लंबाई संशोधक की सूची में C99 जोड़ और चित्रित नहीं किया गया है
Christoph

3
@ क्रिसटोफ: न ही यह नवीनतम ड्राफ्ट, एन 3035 में है।
GMANNICKG

11
@avakar @Adam Rosenfield @Christoph @GMan: हालाँकि, n3035 A1.2 सामान्य संदर्भ में, केवल C99 मानक को संदर्भित किया जाता है, और समान राज्यों के .617.6.1.2 / 3 को "C मानक पुस्तकालय की सुविधाएं प्रदान की जाती हैं।" मैं इसका मतलब यह बताऊंगा कि जब तक अन्यथा निर्दिष्ट नहीं किया जाता है, तब तक C99 मानक पुस्तकालय में सब कुछ C ++ 0x मानक पुस्तकालय का हिस्सा है, जिसमें C99 में अतिरिक्त प्रारूप विनिर्देशक शामिल हैं।
जेम्स मैकनेलिस

9
@ अरुनसाह: यह केवल C99 की विशेषता है, C ++ की नहीं। यदि आप इसे संकलित करना चाहते हैं -pedantic, तो आपको C ++ 1x ड्राफ्ट (अत्यधिक संभावना नहीं) का समर्थन करने वाले एक कंपाइलर की आवश्यकता होगी, या आपको अपने कोड को C99 के रूप में संकलित फ़ाइल में ले जाना होगा। अन्यथा, आपका एकमात्र विकल्प यह है कि आप अपने चरों को अधिकतम पोर्टेबल रूप से unsigned long longउपयोग %lluकरें।
एडम रोसेनफील्ड

88

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

... और हां, अगर आप सी का उपयोग कर रहे ++, आप उपयोग कर सकते हैं coutबजाय के रूप में अरक ने सुझाव दिया


3
zको newlib (यानी cygwin) द्वारा समर्थित किया गया है
Christoph

7
%zdके लिए गलत है size_t; साइन किए गए प्रकार के लिए यह सही है size_t, लेकिन size_tस्वयं एक अहस्ताक्षरित प्रकार है।
कीथ थॉम्पसन

1
@KeithThompson: मैंने भी उल्लेख %zuकिया (और %zxयदि वे हेक्स चाहते हैं)। यह सच है कि %zuसूची में पहले होना चाहिए था। फिक्स्ड।
टीजे क्राउडर

10
@TJCrowder: मुझे नहीं लगता %zdकि सूची में होना चाहिए। मैं मूल्य छापने के %zdबजाय उपयोग करने का कोई कारण नहीं सोच सकता । मान से अधिक होने पर यह मान्य (अपरिभाषित व्यवहार नहीं है) भी नहीं है । (पूर्णता के लिए, आप अष्टक का उल्लेख कर सकते हैं ।)%zusize_tSIZE_MAX / 2%zo
कीथ थॉम्पसन

2
@FUxxxxl: POSIX की आवश्यकता नहीं है कि ssize_tहस्ताक्षरित प्रकार के अनुरूप है size_t, इसलिए यह मैच के लिए गारंटी नहीं है "%zd"। (यह शायद सबसे अधिक कार्यान्वयन पर है।) pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
कीथ थॉम्पसन

59

C89 के लिए, %luमान का उपयोग करें और उसे unsigned longनिम्न करें :

size_t foo;
...
printf("foo = %lu\n", (unsigned long) foo);

C99 के लिए और बाद में, उपयोग करें %zu:

size_t foo;
...
printf("foo = %zu\n", foo);

7
2013 को ध्यान में रखते हुए, "पूर्व C99 के लिए" और "पूर्व C99 के लिए" सुझाव दें: "। सबसे बढ़िया उत्तर।
chux - मोनिका

8
यह मत करो। यह 64 बिट विंडोज पर विफल हो जाएगा जहां size_t 64 बिट और लंबी 32 बिट है।
येट्रिल

1
@ वायट्रिल: 64-बिट विंडो के लिए फिर क्या जवाब है?
जॉन बोडे

1
@ जॉनबोड शायद unsigned long long?
जेम्स

2
या: आप एक पर जा सकते हैं uint64_tऔर फिर PRIu64inttypes.h से मैक्रो का उपयोग कर सकते हैं, जिसमें प्रारूप निर्दिष्ट है।
जेम्स

9

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

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

// 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;
}

VS2015 ने बाइनरी आउटपुट उत्पन्न किए:

1
1
2

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

zu
zx
zd

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

इसके अतिरिक्त, निम्नलिखित C99 / C11 हेडर को छोड़कर, सभी C99 हेडर VS2015 पूर्वावलोकन में उपलब्ध हैं:

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

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

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


VS2013 अपडेट 5 उसी परिणाम का उत्पादन करता है जैसा कि अपडेट 4 ने आपको दिया था।
नाथन किड

6

C ++ में ऐसा करने के बारे में बात करने वालों के लिए जो C99 एक्सटेंशन का समर्थन नहीं करता है, तो मैं दिल से बढ़ावा देने की सलाह देता हूं :: प्रारूप। इससे size_t प्रकार का आकार प्रश्न मूट हो जाता है:

std::cout << boost::format("Sizeof(Var) is %d\n") % sizeof(Var);

चूँकि आपको बढ़ावा देने में आकार के विवरणों की आवश्यकता नहीं है :: प्रारूप, आप केवल इस बात की चिंता कर सकते हैं कि आप किस प्रकार मूल्य प्रदर्शित करना चाहते हैं।


4
शायद चाहते हैं %u
GMNNICKG

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

8
हाँ, लेकिन प्रश्नकर्ता विशेष रूप से एक विशेष के लिए पूछता है printf। मुझे लगता है कि उनके पास कुछ अन्य अड़चनें हैं जो std::coutएक समस्या का उपयोग करती हैं।
डोनाल्ड फेलो

1
@ मुझे आश्चर्य है कि C ++ प्रोजेक्ट में C ++ स्ट्रीम किस तरह की समस्या पैदा कर सकता है!
आरा

9
@AraK। वे बहुत धीमे हैं? वे बहुत कारण नहीं के लिए बहुत सारे बाइट्स जोड़ते हैं। अरुणशाह सिर्फ अपने निजी ज्ञान के लिए जानना चाहते हैं? व्यक्तिगत पसंद (मैं खुद को बहाना करने के लिए stdio पसंद करता हूं)। इसके कई कारण हैं।
कित्सुएनएमजी

1
@TKCrowder: ठीक है, मूल अनुरोध में कहा गया था कि एक C समाधान वांछित था (टैगिंग के माध्यम से) और C ++ में धाराओं का उपयोग न करने के अच्छे कारण हैं, उदाहरण के लिए, यदि आउटपुट स्वरूप डिस्क्रिप्टर को संदेश कैटलॉग से खींचा जा रहा है। (यदि आप चाहते थे, तो आप संदेशों के लिए एक पार्सर लिख सकते हैं और धाराओं का उपयोग कर सकते हैं, लेकिन यह बहुत काम आता है जब आप मौजूदा कोड का लाभ उठा सकते हैं।)
डोनाल्ड फेलो

1
@ डोनल: टैग सी और सी ++ थे। मैं किसी भी तरह से C ++ के I / O स्ट्रीम सामान की वकालत नहीं कर रहा हूं (मैं इसका प्रशंसक नहीं हूं), बस यह इंगित करता हूं कि प्रश्न मूल रूप से नहीं था "" ... एक विनिर्देशक के लिए विनिर्देश पूछें printf। "
TJ क्राउडर


2

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

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

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

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

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

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

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

इसलिए आप सी + + स्ट्रीम, सशर्त संकलन, 3 पार्टी फ्रेमवर्क, या कुछ प्रकार के पोर्टेबल के लिए नीचे हैं जो आपके लिए काम करते हैं।


-1

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

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


1
यदि आप गलत आकार के कुछ प्रिंट में पास करते हैं तो अधिकांश कंपाइलर आपको चेतावनी नहीं देंगे। जीसीसी एक अपवाद है। inttypes.h को C99 में परिभाषित किया गया था इसलिए कोई भी C कंपाइलर जो C99 कंप्लेंट है, उसके पास होगा, जो अब तक सभी को होना चाहिए। फिर भी, आपको संकलक ध्वज के साथ C99 चालू करना पड़ सकता है। किसी भी स्थिति में, intttypes.h size_t या ptrdiff_t के लिए एक विशिष्ट प्रारूप को परिभाषित नहीं करता है, क्योंकि उन्हें क्रमशः 'z' और 't' के अपने आकार के विनिर्देशक प्राप्त करने के लिए पर्याप्त महत्वपूर्ण होने का निर्णय लिया गया था।
स्वैप्ट करें

यदि आप का उपयोग करते हैं %lu, तो आपको size_tमूल्य डालना चाहिए unsigned long। तर्कों के लिए कोई अंतर्निहित रूपांतरण (पदोन्नति के अलावा) नहीं है printf
कीथ थॉम्पसन

-2

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

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

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


2
zआकार modidfier मानक सी है, लेकिन कुछ libc कार्यान्वयन विभिन्न कारणों के लिए 1990 में अटक कर रहे हैं (सी के पक्ष में जैसे माइक्रोसॉफ्ट मूल रूप से परित्यक्त सी ++ और - अभी हाल ही में - सी #)
क्रिस्टोफ

3
C99 ने आकार निर्दिष्ट करने वाले 'z' को 'size_t मान' और 't' का आकार ptrdiff_t मान के आकार के रूप में परिभाषित किया।
swestrup

2
%zdहै गलत है, यह अहस्ताक्षरित तो यह होना चाहिए है %zu
डेविड कॉनराड

-3

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

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


1
ध्यान दें कि लिंक-केवल उत्तर हतोत्साहित किए जाते हैं, एसओ उत्तर एक समाधान के लिए खोज का अंतिम बिंदु होना चाहिए (बनाम संदर्भों का एक और ठहराव, जो समय के साथ बासी हो जाते हैं)। लिंक को संदर्भ के रूप में रखते हुए कृपया यहां एक स्टैंड-अलोन सिनोप्सिस जोड़ने पर विचार करें।
Kleopatra

-5

यदि आप एक स्ट्रिंग के रूप में 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://stackoverflow.com/a/918909/1755794
http: // www। cplusplus.com/reference/cstdio/printf/

size_t एक 32bit मशीन पर अहस्ताक्षरित int और 64bit पर लंबे समय से पहले अहस्ताक्षरित है,
लेकिन% ll हमेशा एक अहस्ताक्षरित लंबे int की अपेक्षा करता है।

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


4
क्या बकवास हे?!
एंटटी हापाला

आकार सारणी सूचक के माध्यम से एक लंबी अहस्ताक्षरित लंबी 64 बिट के लिए चार सरणी का पहला बाइट्स डालना और उन्हें प्रिंटफ% I64d के साथ संख्या के रूप में प्रिंट करना वास्तव में शानदार नहीं है मुझे पता है, निश्चित रूप से मैं टाइप ओवरफ्लो को रोकने के लिए कोड में नहीं था लेकिन यह सवाल के दायरे में नहीं है।
आंद्रे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.