NSInteger için NSLog / printf belirticisi?


131

A NSInteger, 32 bit platformlarda 32 bit ve 64 bit platformlarda 64 bittir. Her NSLogzaman boyutuyla eşleşen bir belirtici var mı NSInteger?

Kurmak

  • Xcode 3.2.5
  • llvm 1.6 derleyici (bu önemlidir; gcc bunu yapmaz)
  • GCC_WARN_TYPECHECK_CALLS_TO_PRINTF açık

Bu bana biraz keder veriyor:

#import <Foundation/Foundation.h>

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

32 bit kod için %dtanımlayıcıya ihtiyacım var . Ancak %dbelirticiyi kullanırsam, 64 bit için derlerken %ldbunun yerine kullanmamı öneren bir uyarı alıyorum .

%ld64 bit boyutunu eşleştirmek için kullanırsam , 32 bit kod için derlerken %dbunun yerine kullanmamı öneren bir uyarı alıyorum .

Her iki uyarıyı aynı anda nasıl düzeltirim? Her ikisinde de çalışan kullanabileceğim bir tanımlayıcı var mı?

Bu aynı zamanda etkiler [NSString stringWithFormat:]ve [[NSString alloc] initWithFormat:].

Yanıtlar:


296

Güncellenen cevap:

Tüm mimariler üzerinde uyarı vermeden ve işlemek için zve tdeğiştiricilerinden yararlanabilirsiniz .NSIntegerNSUInteger

%zdİmzalı, %tuişaretsiz ve %txonaltılık için kullanmak istiyorsunuz .

Bu bilgi, Greg Parker'ın izniyle gelmektedir .


Orijinal cevap:

Resmi tavsiye edilen yaklaşım kullanmaktır %ldsizin belirteç olarak ve fiili argüman döküm için long.


6
Kesinlikle gidilecek yol bu, ama bence kullanabilirim static inline NSIntToLong(NSInteger i) {return (long)i;}. Bu, tür denetimini tamamen devre dışı bırakmayı önler (yani, i türünün değişmesi durumunda).
Steven Fisher

3
@ Steven-fisher'dan iyi fikir. Uyarılardan kaçının:static inline long NSIntToLong(NSInteger i) {return (long)i;}
Erik

3
Ayrıca bir NSNumber oluşturabilir ve bunu günlüğe kaydedebilirsiniz. NSLog(@"%@",@(mynsint)); stackoverflow.com/questions/20355439/…
orkoden

2
@KevinBallard Bu ciddi bir performans sorunu olmamalı. Yine de üretim kodunda çok fazla NSLog kullanmamalısınız. Herhangi bir nedenle çok fazla şey kaydetmeniz gerekiyorsa, bunu ayrı bir iş parçacığında yapın.
orkoden

4
Xcode 9.3'ten itibaren NSInteger'ı bir format bağımsız değişkeni olarak kullanırken bir uyarı var %zd:Values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead
Rob MacEachern

2

Kabul edilen cevap kesinlikle makul, standartlara uygun ve doğrudur. Tek sorun, artık çalışmamasıdır, bu tamamen Apple'ın hatasıdır.

% Zd biçimi, size_t ve ssize_t için C / C ++ standart biçimidir. NSInteger ve NSUInteger gibi, size_t ve ssize_t 32 bit sistemde 32 bit ve 64 bit sistemde 64 bittir. İşte bu yüzden NSInteger ve NSUInteger'ı% zd kullanarak yazdırmak işe yaradı.

Bununla birlikte, NSInteger ve NSUInteger, 64 bitlik bir sistemde "long" ve 32 bitlik bir sistemde "int" (64'e karşı 32 bit) olarak tanımlanır. Bugün, size_t hangi tüm sistemlerde "Uzun" tanımlanır olan NSInteger (ya 64 ya da 32 bit) aynı boyutta, ancak farklı bir türü. Ya Apple'ın uyarıları değişti (bu nedenle, doğru sayıda bite sahip olmasına rağmen, yanlış türün printf'e geçmesine izin vermiyor) ya da size_t ve ssize_t için temel türler değişti. Hangisi olduğunu bilmiyorum ama% zd bir süre önce çalışmayı bıraktı. Orada hiçbir biçim hem 32 hem de 64 bit sistemlerde uyarı olmadan NSInteger yazdırır bugün.

Maalesef yapabileceğiniz tek şey:% ld kullanın ve değerlerinizi NSInteger'dan long'a veya NSUInteger'dan unsigned long'a çevirin.

Artık 32 bit için geliştirme yapmadığınızda, herhangi bir cast olmadan sadece% ld kullanabilirsiniz.


0

Biçimlendiriciler, standart UNIX / POSIX printf işlevinden gelir. Kullanım % lu için işaretsiz uzun , uzun süre% ld, uzun uzun% lld ve % llu için işaretsiz uzun uzun . Konsolda man printf'i deneyin, ancak Mac'te eksik. Linux yönetim sayfaları daha belirgindir http://www.manpages.info/linux/sprintf.3.html

Her iki uyarı da sadece NSLog (@ "% lu", (unsigned long) arg) tarafından düzeltilebilir; kod, iOS için 32 VE 64 bit olarak derleneceği için bir döküm ile birlikte. Aksi takdirde her derleme ayrı bir uyarı oluşturur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.