web-dev-qa-db-ja.com

Objective-C:BOOL vs bool

「新しいタイプ」BOOLYESNO)を見ました。

私はこのタイプがほとんどcharに似ていると読んだ。

テストのために:

NSLog(@"Size of BOOL %d", sizeof(BOOL));
NSLog(@"Size of bool %d", sizeof(bool));

両方のログに「1」が表示されることを確認してください(C++のboolはintで、sizeofが4である場合があります)

だから私は、boolタイプか何かに問題があるのではないかと思っていましたか?

速度を落とさずにbool(動作しているように見える)を使用できますか?

187
Francescu

objc.hの定義から:

#if (TARGET_OS_IPHONE && __LP64__)  ||  TARGET_OS_WATCH
typedef bool BOOL;
#else
typedef signed char BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used.
#endif

#define YES ((BOOL)1)
#define NO  ((BOOL)0)

したがって、はい、BOOLはcharであると仮定できます。 (C99)bool型を使用できますが、AppleのObjective-CフレームワークとほとんどのObjective-C/CocoaコードはすべてBOOLを使用するため、BOOLを使用するだけでtypedefが変更されても頭痛の種はなくなります。

194
Barry Wark

上記のように、BOOLは署名された文字です。 bool-C99標準(int)からの型。

ブール-はい/いいえ。 bool-true/false。

例を参照してください:

bool b1 = 2;
if (b1) printf("REAL b1 \n");
if (b1 != true) printf("NOT REAL b1 \n");

BOOL b2 = 2;
if (b2) printf("REAL b2 \n");
if (b2 != YES) printf("NOT REAL b2 \n");

そして結果は

リアルb1
REAL b2
NOT REAL b2

Bool!= BOOLであることに注意してください。以下の結果は一度だけ-REAL b2のみです

b2 = b1;
if (b2) printf("ONCE AGAIN - REAL b2 \n");
if (b2 != true) printf("ONCE AGAIN - NOT REAL b2 \n");

BoolをBOOLに変換する場合は、次のコードを使用する必要があります

BOOL b22 = b1 ? YES : NO; //and back - bool b11 = b2 ? true : false;

したがって、私たちの場合:

BOOL b22 = b1 ? 2 : NO;
if (b22)    printf("ONCE AGAIN MORE - REAL b22 \n");
if (b22 != YES) printf("ONCE AGAIN MORE- NOT REAL b22 \n");

それで..今何が得られますか? :-)

33
beryllium

これを書いている時点では、これはobjc.hの最新バージョンです。

/// Type to represent a boolean value.
#if (TARGET_OS_IPHONE && __LP64__)  ||  TARGET_OS_WATCH
#define OBJC_BOOL_IS_BOOL 1
typedef bool BOOL;
#else
#define OBJC_BOOL_IS_CHAR 1
typedef signed char BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used.
#endif

つまり、64ビットiOSデバイスおよびWatchOS BOOLboolとまったく同じですが、他のすべてのデバイス(OS X、32ビットiOS)ではsigned charであり、コンパイラフラグ-funsigned-charでオーバーライドすることさえできません。

また、このコード例はプラットフォームごとに異なる方法で実行されることを意味します(自分でテストしました)。

int myValue = 256;
BOOL myBool = myValue;
if (myBool) {
    printf("i'm 64-bit iOS");
} else {
    printf("i'm 32-bit iOS");
}

ところで、可能な値の約0.4%が負になるため、array.countのようなものをBOOL変数に割り当てることはありません。

11
Tobol

使用すべきObjective-CタイプはBOOLです。ネイティブのブールデータ型のようなものはありません。そのため、すべてのコンパイラでコードがコンパイルされるようにするには、BOOLを使用します。 (Apple-Frameworksで定義されています。

8
Georg Schölly

うん、BOOLはobjc.hによる符号付き文字のtypedefです。

しかし、boolについては知りません。それはC++のことですよね? 1がYES/trueであり、0がNO/falseである符号付き文字として定義されている場合、どちらを使用しても問題ないと思います。

ただし、BOOLはObjective-Cの一部であるため、明確にするためにBOOLを使用する方がおそらく理にかなっています(他のObjective-C開発者は、使用中のboolを見ると困惑するかもしれません)。

5
Jeff

BoolとBOOLのもう1つの違いは、キーと値の監視を行うとき、または-[NSObject valueForKey:]などのメソッドを使用するとき、同じ種類のオブジェクトに正確に変換しないことです。

誰もがここで言ったように、BOOLはcharです。そのため、charを保持するNSNumberに変換されます。このオブジェクトは、「A」や「\ 0」などの通常の文字から作成されたNSNumberと区別できません。元々BOOLだった情報を完全に失いました。

ただし、boolはCFBooleanに変換され、NSNumberと同じように動作しますが、オブジェクトのboolean Originは保持されます。

私はこれがブール対ブールの議論の議論だとは思わないが、これはいつかあなたを噛むかもしれない。

一般的に言えば、これはCocoa/iOS API(C99とそのネイティブbool型の前に設計された)のすべてで使用される型であるため、BOOLを使用する必要があります。

4
Gwendal Roué

受け入れられた回答は編集されており、その説明は少し間違っています。コードサンプルは更新されましたが、以下のテキストは同じままです。 BOOLはアーキテクチャとプラットフォームに依存するため、現時点ではBOOLであると想定することはできません。したがって、32ビットプラットフォーム(iPhone 5など)でコードを実行し、@ encode(BOOL)を出力すると、「c」が表示されます。 char type に対応します。ただし、iPhone 5s(64ビット)でコードを実行すると、「B」が表示されます。 bool type に対応します。

2
curious

前述のように、BOOLは、アーキテクチャによってはunsigned char型であり、boolint型です。簡単な実験で、BOOLとboolの動作が異なる理由を示します。

bool ansicBool = 64;
if(ansicBool != true) printf("This will not print\n");

printf("Any given vlaue other than 0 to ansicBool is evaluated to %i\n", ansicBool);

BOOL objcBOOL = 64;
if(objcBOOL != YES) printf("This might print depnding on your architecture\n");

printf("BOOL will keep whatever value you assign it: %i\n", objcBOOL);

if(!objcBOOL) printf("This will not print\n");

printf("! operator will zero objcBOOL %i\n", !objcBOOL);

if(!!objcBOOL) printf("!! will evaluate objcBOOL value to %i\n", !!objcBOOL);

驚いたことに、if(objcBOOL != YES)はコンパイラによって1に評価されます。これはYESが実際に文字コード1であり、コンパイラの観点からすると、文字コード64はもちろんnot equal文字コード1の場合、ifステートメントはYES/true/1と評価され、次の行が実行されます。ただし、ゼロ以外のbool型は常に整数値1に評価されるため、上記の問題はコードに影響しません。 Objective-C BOOL型とANSI C bool型を使用する場合の良いヒントを次に示します。

  • 常にYESまたはNOの値を割り当ててください。
  • 予期しない結果を避けるため、!!演算子ではなくdoubleを使用してBOOL型を変換します。
  • YESを確認するときはif(!myBool) instead of if(myBool != YES)を使用しますが、not !演算子を使用する方がずっときれいで、期待どおりの結果が得られます。
1
ilgaar

ここで慣例に反します。 typedefの基本型が好きではありません。私はそれが価値を削除する役に立たない間接化だと思う。

  1. ソースにベースタイプが表示されたら、すぐに理解できます。 typedefの場合は、実際に処理しているものを確認するために検索する必要があります。
  2. 別のコンパイラに移植したり、別のライブラリを追加すると、typedefのセットが競合し、デバッグが困難な問題が発生する可能性があります。私は実際にこれに対処し終わったところです。 1つのライブラリではブール値がintにtypedefされ、mingw/gccではcharにtypedefされました。
1
Jay

また、特にビットマスクを使用する場合は、signed charへのキャストによるキャストの違いに注意してください。

bool a = 0x0100;
a == true;  // expression true

BOOL b = 0x0100;
b == false; // expression true on !((TARGET_OS_IPHONE && __LP64__) || TARGET_OS_WATCH), e.g. MacOS
b == true;  // expression true on (TARGET_OS_IPHONE && __LP64__) || TARGET_OS_WATCH

BOOLがブールではなく符号付き文字である場合、BOOLへの0x0100のキャストは単にセットビットをドロップし、結果の値は0です。

0
michaf