0

サンプル コードの Objective-C の性質については申し訳ありませんが、私の質問に対する答えは、C 標準ライブラリおよび/または Appleclangコンパイラ内にあると確信しています。

NSArray可変数のアイテムが含まれています。項目数を使用して 1 から 3 の間の値を作成したいと考えています。CMAXマクロを使用していますが、奇妙な動作があります。

NSLog( @"%d %d %d %d", 1, [tasks count], 3 - [tasks count], MAX( 1, 3 - [tasks count] ) );

アイテムの数を増やしたときのこのログ ステートメントの出力tasksは次のとおりです。

1 0 3 3
1 1 2 2
1 2 1 1
1 3 0 1
1 4 -1 -1

ドキュメントを少し調べたところ、count関数が を返していることがわかりましたNSUInteger。私のジレンマの解決策は、戻り値をNSInteger次のように型キャストすることです。

NSLog( @"%d %d %d %d", 1, (NSInteger)[tasks count], 3 - (NSInteger)[tasks count], MAX( 1, 3 - (NSInteger)[tasks count] ) );

1 0 3 3
1 1 2 2
1 2 1 1
1 3 0 1
1 4 -1 1

(Objective-C に慣れていない場合は、32 ビット アーキテクチャではおよびがNSIntegertypedef されます。)intNSUIntegerunsigned int

元のコードで暗黙的に発生した型キャストを理解するのに苦労しており、直感的でない結果につながっています。誰でも点灯できますか?

4

2 に答える 2

2

コンパイラの警告をオンにします。あなたが言うように、Objective Cビットは無関係なので、これからCを参照します。

マクロがこのように定義されているとしましょうMAX()(GCC拡張機能を使用):

#define MAX(x, y) ({ typeof (x) _x = (x); \
                     typeof (y) _y = (y); \
                     _x > _y ? _x : _y })

MAX()マクロは非標準です

を計算するMAX(1, 3 - [tasks count])と、次のようになります。

int x = 1;
unsigned y = 3 - [tasks count];
x > y ? x : y;

intこれで、Cでanとanを適切に比較できますunsignedが、Cで使用した場合の動作ではありませんx > y。代わりに、両方のオペランドがに変換されますunsigned(「通常の算術変換」のため)。

したがって、比較は(unsigned) 1 > (unsigned) -1であり、これは誤りです。これは、ほとんどのシステム(32ビットと64ビットの両方)で(unsigned) -1可能な最大のであるためです。unsigned0xffffffff

エラーはどこにありますか?

NSLog(@"%d", [tasks count]);

これは技術的に間違っています。に渡しunsignedていますが、の形式指定子をNSLog()使用しています。代わりに使用するか、値を最初にキャストしてください。%dint%uint

コンパイラの警告

コンパイラは2つの警告を出します:

  • を計算するときに、符号付きと符号なしを比較していることがわかりますMAX(1, 3 - [tasks count])

  • フォーマットが。を期待するときににunsignedを渡すことを通知します。NSLog()int

于 2013-02-20T22:36:36.087 に答える
2

3 - [タスク数] は unsigned 型で行われるため、減算がラップアラウンドし、0xffffffff になります。したがって、符号なしの型で MAX(1, 0xffffffff) を取得します。

ただし、NSLog フォーマット文字列が「%d」であるため、これを符号付き整数として出力すると、NSLog は引数のビットを符号付き整数として扱い、ビット パターン 0xffffffff は -1 になります。

于 2013-02-20T22:35:35.933 に答える