NSInteger के लिए NSLog / printf विनिर्देशक?


131

A NSInteger32-बिट प्लेटफॉर्म पर 32 बिट्स और 64-बिट प्लेटफॉर्म पर 64 बिट्स है। क्या कोई ऐसा NSLogविनिर्देशक है जो हमेशा के आकार से मेल खाता है NSInteger?

सेट अप

  • Xcode 3.2.5
  • llvm 1.6 संकलक (यह महत्वपूर्ण है; gcc ऐसा नहीं करता है)
  • GCC_WARN_TYPECHECK_CALLS_TO_PRINTF कामोत्तेजित

मुझे यहाँ कुछ दुःख हो रहा है:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    @autoreleasepool {
        NSInteger i = 0;
        NSLog(@"%d", i);
    }
    return 0;
}

32 बिट कोड के लिए, मुझे %dविनिर्देशक की आवश्यकता है । लेकिन अगर मैं %dविनिर्देशक का उपयोग करता हूं, तो मुझे 64 बिट के लिए संकलन करते समय चेतावनी दी जाती है कि मैं %ldइसके बजाय उपयोग करता हूं ।

यदि मैं %ld64 बिट आकार से मेल खाने के लिए उपयोग करता हूं , तो 32 बिट कोड के लिए संकलन करने पर मुझे चेतावनी मिलती है कि मैं %dइसके बजाय उपयोग करने का सुझाव देता हूं ।

मैं एक बार में दोनों चेतावनियाँ कैसे ठीक करूँ? क्या कोई स्पेसिफ़ायर है जो मैं या तो काम करता है?

यह भी प्रभाव डालता है [NSString stringWithFormat:]और [[NSString alloc] initWithFormat:]

जवाबों:


296

अद्यतन उत्तर:

आप का उपयोग कर सकते zहैं और tसंभाल करने के लिए संशोधक NSIntegerऔर NSUIntegerसभी आर्किटेक्चर पर चेतावनी के बिना,।

आप %zdहस्ताक्षरित के लिए, %tuअहस्ताक्षरित और %txहेक्स के लिए उपयोग करना चाहते हैं ।

यह जानकारी ग्रेग पार्कर के सौजन्य से आई है ।


मूल उत्तर:

आधिकारिक सिफारिश की दृष्टिकोण का उपयोग करना है %ldअपने विनिर्देशक के रूप में, और एक वास्तविक तर्क कास्ट करने के लिए long


6
यह निश्चित रूप से जाने का रास्ता है, लेकिन मुझे लगता है कि मैं उपयोग कर सकता हूं static inline NSIntToLong(NSInteger i) {return (long)i;}। यह पूरी तरह से जाँच को अक्षम करने से बचता है (अर्थात यदि मैं बदल जाता है)।
स्टीवन फिशर

3
@ स्टीवन-फिशर द्वारा अच्छी सोच। इसके साथ चेतावनी से बचें:static inline long NSIntToLong(NSInteger i) {return (long)i;}
एरिक

3
आप एक NSNumber भी बना सकते हैं और लॉग इन कर सकते हैं। NSLog(@"%@",@(mynsint)); stackoverflow.com/questions/20355439/…
orkoden

2
@KevinBallard यह एक गंभीर प्रदर्शन मुद्दा नहीं होना चाहिए। आपको वैसे भी बहुत सारे NSLog का उत्पादन कोड में उपयोग नहीं करना चाहिए। यदि आपको किसी कारण से बहुत सारे सामान को लॉग करना है, तो इसे अलग थ्रेड पर करें।
orkoden

4
Xcode 9.3 तक NSInteger को एक प्रारूप तर्क के रूप में उपयोग करते समय एक चेतावनी है %zd:Values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead
Rob MacEachern

2

स्वीकृत उत्तर बिल्कुल उचित है, यह मानक अनुरूप है, और सही है। एकमात्र समस्या यह है कि यह अब काम नहीं करता है, जो पूरी तरह से Apple की गलती है।

स्वरूप% zd आकार / t और ssize_t के लिए C / C ++ मानक प्रारूप है। NSInteger और NSUInteger की तरह, size_t और ssize_t 32 बिट सिस्टम पर 32 बिट, और 64 बिट सिस्टम पर 64 बिट हैं। और यही कारण है कि% zd का उपयोग करके NSInteger और NSUInteger को प्रिंट करना काम किया।

हालाँकि, NSInteger और NSUInteger को 64 बिट सिस्टम पर "लॉन्ग" और 32 बिट सिस्टम पर "int" के रूप में परिभाषित किया गया है (जो 64 बनाम 32 बिट है)। आज, size_t सभी सिस्टम पर "लंबे समय" पर परिभाषित किया गया है, जो है NSInteger (या तो 64 या 32 बिट) के रूप में एक ही आकार, लेकिन एक अलग प्रकार का। या तो Apple की चेतावनियाँ बदल गई हैं (इसलिए यह गलत प्रकार को प्रिंटफ़ में पास करने की अनुमति नहीं देता है, भले ही इसमें बिट्स की सही संख्या हो), या size_t और ssize_t के लिए अंतर्निहित प्रकार बदल गए हैं। मुझे नहीं पता कि कुछ समय पहले, लेकिन% zd ने काम करना बंद कर दिया था। नहीं है कोई प्रारूप आज है कि दोनों 32 और 64 बिट सिस्टम पर बिना किसी चेतावनी के NSInteger प्रिंट होगा।

तो केवल एक चीज जो आप दुर्भाग्य से कर सकते हैं:% ld का उपयोग करें, और अपने मूल्यों को NSInteger से लंबे समय तक, या NSUInteger से लंबे समय तक अनसाइन करें।

एक बार जब आप 32 बिट के लिए निर्माण नहीं करते हैं, तो आप बस बिना किसी कास्ट के,% ld का उपयोग कर सकते हैं।


0

स्वरूपक मानक UNIX / POSIX प्रिंटफ फ़ंक्शन से आते हैं। अहस्ताक्षरित लंबे समय के लिए % लू का उपयोग करें , लंबे समय के लिए % एलडी, लंबे समय के लिए% एलडी, और बिना लंबे समय के लिए % लुल्ल का उपयोग करें । कंसोल पर मैन प्रिंटफ़ की कोशिश करें, लेकिन मैक पर यह अधूरा है। Linux manpages अधिक स्पष्ट हैं http://www.manpages.info/linux/sprintf.3.html

दोनों चेतावनियाँ केवल NSLog (@ "% lu", (अहस्ताक्षरित लंबी) arg) द्वारा तय की जा सकती हैं; कोड के रूप में एक कास्ट के साथ संयुक्त आईओएस के लिए 32 और 64 बिट में संकलित किया जाएगा। अन्यथा प्रत्येक संकलन एक अलग चेतावनी बनाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.