A NSInteger
adalah 32 bit pada platform 32-bit, dan 64 bit pada platform 64-bit. Apakah ada NSLog
specifier yang selalu cocok dengan ukuran NSInteger
?
Mempersiapkan
- Xcode 3.2.5
- llvm 1.6 compiler (ini penting; gcc tidak melakukan ini)
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF
dihidupkan
Itu membuat saya sedih di sini:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
@autoreleasepool {
NSInteger i = 0;
NSLog(@"%d", i);
}
return 0;
}
Untuk kode 32 bit, saya perlu %d
specifier. Tetapi jika saya menggunakan %d
specifier, saya mendapat peringatan ketika mengkompilasi untuk 64 bit menyarankan saya gunakan %ld
sebagai gantinya.
Jika saya gunakan %ld
untuk mencocokkan ukuran 64 bit, ketika mengkompilasi kode 32 bit saya mendapatkan peringatan yang menyarankan saya gunakan %d
sebagai gantinya.
Bagaimana cara saya memperbaiki kedua peringatan sekaligus? Apakah ada specifier yang bisa saya gunakan yang berfungsi baik?
Ini juga berdampak [NSString stringWithFormat:]
dan [[NSString alloc] initWithFormat:]
.
sumber
static inline NSIntToLong(NSInteger i) {return (long)i;}
. Ini menghindari pemeriksaan penonaktifan tipe sepenuhnya (yaitu jika jenis i berubah).static inline long NSIntToLong(NSInteger i) {return (long)i;}
NSLog(@"%@",@(mynsint));
stackoverflow.com/questions/20355439/…%zd
:Values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead
Jawaban yang diterima benar-benar masuk akal, sesuai standar, dan benar. Satu-satunya masalah adalah bahwa itu tidak berfungsi lagi, yang sepenuhnya merupakan kesalahan Apple.
Format% zd adalah format standar C / C ++ untuk size_t dan ssize_t. Seperti NSInteger dan NSUInteger, size_t dan ssize_t adalah 32 bit pada sistem 32 bit, dan 64 bit pada sistem 64 bit. Dan itu sebabnya pencetakan NSInteger dan NSUInteger menggunakan% zd bekerja.
Namun, NSInteger dan NSUInteger didefinisikan sebagai "panjang" pada sistem 64 bit, dan sebagai "int" pada sistem 32 bit (yaitu 64 vs 32 bit). Hari ini, size_t didefinisikan pada "lama" pada semua sistem, yang merupakan ukuran yang sama seperti NSInteger (baik 64 atau 32 bit), tapi jenis yang berbeda. Entah peringatan Apple telah berubah (jadi itu tidak memungkinkan melewatkan jenis yang salah ke printf, meskipun memiliki jumlah bit yang tepat), atau jenis yang mendasari untuk size_t dan ssize_t telah berubah. Saya tidak tahu yang mana, tetapi% zd berhenti bekerja beberapa waktu yang lalu. Tidak ada format hari ini yang akan mencetak NSInteger tanpa peringatan pada sistem 32 dan 64 bit.
Jadi satu-satunya hal yang dapat Anda lakukan sayangnya: Gunakan% ld, dan berikan nilai Anda dari NSInteger ke long, atau dari NSUInteger ke long unsigned.
Setelah Anda tidak membuat 32 bit lagi, Anda bisa menggunakan% ld, tanpa gips.
sumber
Pemformat berasal dari fungsi printf standar UNIX / POSIX. Gunakan % lu untuk panjang yang tidak ditandatangani ,% ld untuk panjang,% lld untuk panjang panjang, dan % llu untuk panjang tidak ditandatangani . Coba printf man di konsol, tetapi pada Mac itu tidak lengkap. Linux manpages lebih eksplisit http://www.manpages.info/linux/sprintf.3.html
Kedua peringatan hanya dapat diperbaiki oleh NSLog (@ "% lu", (unsigned long) arg); dikombinasikan dengan para pemain sebagai kode akan dikompilasi dalam 32 DAN 64 bit untuk iOS. Kalau tidak, setiap kompilasi membuat peringatan terpisah.
sumber