NSInteger myInt = 1804809223;
NSLog(@"%i", myInt); <====
上記のコードはエラーを生成します:
Values of type "NSInteger" should not be used as format arguments: add an explicit cast to 'long' instead.
正しいNSLog
メッセージは実際にはNSLog(@"%lg", (long) myInt);
です。値を表示したい場合、なぜmyIntの整数値をlongに変換する必要があるのですか?
OS X(64ビット)でコンパイルすると、このプラットフォームでNSInteger
がlong
として定義され、64ビット整数であるため、この警告が表示されます。一方、%i
形式はint
用であり、32ビットです。そのため、形式と実際のパラメーターのサイズが一致しません。
NSInteger
はプラットフォームに応じて32ビットまたは64ビットであるため、一般的にコンパイラはlong
にキャストを追加することをお勧めします。
更新: iOS 7は64ビットもサポートするようになったため、iOS用にコンパイルするときに同じ警告を受け取ることができます。
書式指定子がデータ型と一致する場合、何にもキャストする必要はありません。ネイティブ型NSInteger
が定義されているMartin Rの回答を参照してください。
OS X 64ビットでは、次のようにログステートメントを記述できます。
NSLog(@"%ld", myInt);
iOSでは次のことができます:
NSLog(@"%d", myInt);
そして、キャストなしですべて動作します。
とにかく、少なくとも非UIコードでキャストを使用する理由の1つは、プラットフォーム間で適切なコードが移植される傾向があり、変数を明示的にキャストすると、32ビットと64ビットの両方できれいにコンパイルされることです:
NSLog(@"%ld", (long)myInt);
また、これは、iOSコードが64ビットに移行する際にiOSコードに移行する場合に役立ちます。または、iOSとOS Xが一緒にマージされるとき。
NSLogステートメントだけでなく、これは結局デバッグの助けになるだけでなく、[NSString stringWithFormat:]
および生産コードの正当な要素である友人にも当てはまります。
NSIntegerをNSLogに渡す代わりに、NSNumberを渡します。これにより、すべてのキャストが回避され、適切な文字列形式指定子が選択されます。
NSNumber foo = @9000;
NSLog(@"foo: %@", foo);
NSInteger bar = 9001;
NSLog(@"bar: %@", @(bar));
また、それを心配することなく、NSUIntegersでも機能します。 64ビット/ 32ビットが混在する環境でのNSIntegerおよびNSUInteger への回答を参照してください
NSLog(@"%ld", (long)myInt);
を使用している間は警告を保持しますが、iOS 10でlong myInt = 1804809223;
に宣言を変更すると警告を停止します。