web-dev-qa-db-ja.com

NSIntegerおよびNSUInteger(64ビット/ 32ビットの混合環境)

NSLog/NSAssertなどの呼び出しで、かなりの量の文字列フォーマット指定子があります。これらは、それぞれNSInteger (= int on 32bit)およびNSUInteger (= unsigned int on 32bit)タイプで%dおよび%uを使用します。

アプリを64ビットに変換すると、longおよび%ld %luタイプになったものに対してunsigned longが期待されるため、これは警告を出します(もちろん)。

もちろん、フォーマット指定子を変換するだけで、32ビットビルドで逆の警告が発生します。
したがって、警告なしになると私が思う唯一の解決策は、64ビット指定子を使用し、32ビットビルドで警告が出されるすべての場所で64ビット値型にキャストすることです。

しかし、おそらくNSIntegerおよびNSUIntegerタイプ専用のフォーマット指定子があり、キャストせずに両方のアーキテクチャで機能するかどうか疑問に思っていましたか?

28
Pieter

私はそれらをNSNumberインスタンスにボックス化するのが最も安全な方法だと思います。

NSLog(@"Number is %@", @(number)); // use the highest level of abstraction

タグ付きポインタ マジックのおかげで、このボクシングは通常、新しいオブジェクトを作成する必要はありません。

reallyNSNumberを使用したくない場合は、他の人が提案したように、プリミティブ型を手動でキャストできます。

NSLog(@"Number is %ld", (long)number); // works the same on 32-bit and 64-bit
60
ilya n.

コンソールにログインするときに、%zdNSInteger)および%tuNSUInteger)を使用することもできます。

NSInteger integer = 1;
NSLog(@"first number: %zd", integer);

NSUInteger uinteger = 1;
NSLog(@"second number: %tu", uinteger);

ここにもあります。

38
d0m1n1k

いいえ、(残念ながら)NS(U)Integerに直接対応するprintf形式はありません。したがって、アーキテクチャに依存しないコードの場合、すべてを「長い」バリアントに変換する必要があります(Xcodeの「Fix-it」が示唆するように)。

NSInteger i = ...;
NSLog(@"%ld", (long)i);

私が知っている唯一の選択肢は arm64および32ビットアーキテクチャ用にコンパイルするときの基礎タイプ からのものです。

// In the precompiled header file:
#if __LP64__
#define NSI "ld"
#define NSU "lu"
#else
#define NSI "d"
#define NSU "u"
#endif

NSInteger i = ...;
NSLog(@"i=%"NSI, i);

プリプロセッサマクロを使用する(ただし、その回答の作成者でさえ、「明らかにひどいアプローチ」と呼んでいます)。

4
Martin R