web-dev-qa-db-ja.com

NSInteger変数をフォーマット引数として使用するときにlongにキャストする必要があるのはなぜですか?

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に変換する必要があるのですか?

141
Daniel Lee

OS X(64ビット)でコンパイルすると、このプラットフォームでNSIntegerlongとして定義され、64ビット整数であるため、この警告が表示されます。一方、%i形式はint用であり、32ビットです。そのため、形式と実際のパラメーターのサイズが一致しません。

NSIntegerはプラットフォームに応じて32ビットまたは64ビットであるため、一般的にコンパイラはlongにキャストを追加することをお勧めします。

更新: iOS 7は64ビットもサポートするようになったため、iOS用にコンパイルするときに同じ警告を受け取ることができます。

191
Martin R

書式指定子がデータ型と一致する場合、何にもキャストする必要はありません。ネイティブ型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:]および生産コードの正当な要素である友人にも当てはまります。

36
Monolo

NSIntegerをNSLogに渡す代わりに、NSNumberを渡します。これにより、すべてのキャストが回避され、適切な文字列形式指定子が選択されます。

NSNumber foo = @9000;
NSLog(@"foo: %@", foo);
NSInteger bar = 9001;
NSLog(@"bar: %@", @(bar));

また、それを心配することなく、NSUIntegersでも機能します。 64ビット/ 32ビットが混在する環境でのNSIntegerおよびNSUInteger への回答を参照してください

22
orkoden

NSLog(@"%ld", (long)myInt);を使用している間は警告を保持しますが、iOS 10でlong myInt = 1804809223;に宣言を変更すると警告を停止します。

0
Yao Li