Objective-C:BOOL vs bool


192

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

私はこのタイプはほとんどイワシのようだと読んだ。

テストのために私はしました:

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

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

だから私はちょうどブール型か何かにいくつかの問題があるのだろうかと思っていましたか?

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

回答:


198

の定義から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が変更された場合でも頭痛を軽減できます。


17
「アップルのすべてのフレームワーク」-真実ではない。具体的には、CGGeometry.hを見てください:CG_INLINE bool __CGPointEqualToPoint(CGPoint point1、CGPoint point2){return point1.x == point2.x && point1.y == point2.y; }
エリオット

58
@Elliotあなたは正しいです。Cフレームワークの多く(CoreFoundation、CoreGraphicsなど)はC99を使用していboolます。Objective-Cフレームワークはすべてを使用しますBOOL
Barry Wark、2010

@CœurBOOLコードサンプルの定義を編集しましたが、以下のテキストは同じままです。これは少し混乱し、正しくありません。私の答えを見てください。
2016

さまざまな動作を知るには、以下をご覧ください。 NSInteger progressTime = 2;//any value NSInteger totalTime = 1;//any value BOOL success = (progressTime>=totalTime)//それは常に与えられますが、型にNO その(progressTime>=totalTime)値を受け取ると 、正しい結果を返します。私はこの行動を理解していません。私が使用しており、バージョンはでした。@BarryWarkboolsuccessXcode 7.xiOS8.x
カマーシャッド

34

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

BOOL-はい/いいえ。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");

そして結果は

REAL b1
REAL b2
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");

そして、..私たちは今何を得るのですか?:-)


3
三項演算子を使用する代わりに、を使用できます!!b1。それらの間で変換するには
Richard

1
「NOT REAL b2」が私のiPhone SEシミュレータに印刷されていません。
ガブラー

12

執筆時点では、これは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上にあることを意味BOOL全く同じものであるようなbool他のすべてのデバイス(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.countBOOL変数に変数などを割り当てることはありません。


iOS 32ビット(iPhone 5C ...)用にコンパイルするときに、BOOL(UIViewアニメーションブロックなど)を取得するように定義されているブロックのパラメーターとしてboolを使用すると、コンパイラーはエラーを発生させます。私はコードのあらゆる場所でC ++ boolを使用し、BOOL
stephane kで

8

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


2
これは厳密には正確ではありません。フレームワークではなくBOOL、Objective-C言語(objc/*.hヘッダーの1つにあります)によって定義されます。また、C99でコンパイルすると(デフォルトだと思います)、ネイティブのブール型があります_Bool(または含まれているbool場合stdbool.h)。
dreamlax

5

うん、BOOLはobjc.hによると、signed charのtypedefです。

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

ただし、BOOLはObjective-Cの一部であるため、わかりやすくするためにBOOLを使用する方が理にかなっています(他のObjective-C開発者がboolの使用を見ると困惑する場合があります)。


6
_BoolはC99で定義され、標準ヘッダーstdbool.hでマクロboolが定義され(これは_Boolに展開されます)、true / falseもここで定義されます。
ブライアンミッチェル

4

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

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

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

私はこれがBOOL対boolの議論での議論であるとは思わないが、これはいつかあなたに噛みつくかもしれない。

これは、Cocoa / iOS API(C99およびそのネイティブのブール型の前に設計された)のあらゆる場所で使用される型であるため、一般的には、ブール型を使用する必要があります。


2

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


1

ここでは慣習に反対します。typedefを基本型にするのは好きではありません。価値を取り除くのは無用な間接法だと思います。

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

4
まあ...あなたはあなたの言語の標準のtypedef(と思う)を知っていると期待することができsize_tbool(C99)とBOOL(ObjC)の両方がそのカテゴリに分類されます。typedefの変更が原因でコードが失敗した場合は、typedefを不透明なものとして処理せず、1つのプラットフォームでの実装に依存していたため、コードのせいにします。(恥ずかしいことは何もありませんが、起こりますが、それはtypedefではありません。)
DevSolar

1
「標準」のtypedefはあまり標準的ではないようです(たとえば、しばらくの間、MSはposix標準をサポートしていませんでした)。typedefを使用しない場合、typedefが変更されるか、コンパイラーごとに異なるという問題は解消されます。
ジェイ

1
-1、typedefは一般に(特に)2つの重要な目的を果たします。適切なセマンティクスを提供することと、いくつかの誤った方向を提供することです。理想的には、typedefが参照する基本型を知る必要はないはずです。残念ながら、このシステムは完全ではなく、時には知っておく必要があります。私の要点は、完璧ではないことを認めても、代替案よりも優れているため、慣習に従うべきです。
ジョアン・ポルテラ

2
@ジェイ:申し訳ありませんが、私はなぜこの「ミスディレクション」が良いのかを説明するべきでした。私は例を提供しようとします:intまたはcharを直接使用する代わりにtypedefされたブール値を使用する場合は、コードを壊すことなく、各プラットフォームで異なるタイプ(まだ機能します)を使用できるようにします[理由これは変化しますが、charがメモリ内で誤って整列され、その結果として遅くなる可能性があるため、代わりにintがブール値に使用されるプラットフォームを想像できます。
ジョアン・ポルテラ

2
@ジェイ:「良いセマンティクス」とは、ブール値を宣言するBOOL varname代わりにchar varname、その変数の2つの有効な値がtrue/ YESまたはfalse/ であることがより明白であることを意味しますNO
ジョアン・ポルテラ

1

上記のようBOOLに、はタイプですがunsigned char、アーキテクチャによってはタイプになる場合があります。簡単な実験により、BOOLとboolの動作が異なる理由がわかります。boolint

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)YES実際には文字コード1 であるため、コンパイラーは1と評価します。コンパイラーの観点では、文字コード64はもちろん文字コード1 と等しくないため、ifステートメントはYES/true/1次のように評価され、次の行は実行します。ただし、ゼロなしのboolタイプは常に整数値1に評価されるため、上記の問題はコードに影響しません。Objective-C BOOLタイプとタイプを使用したい場合のヒントを以下に示しますANSI C bool

  • 常にYESor NO値を割り当て、それ以外は何も割り当てません。
  • BOOLdouble not !!演算子を使用して型を変換し、予期しない結果を回避します。
  • YES使用をチェックするif(!myBool) instead of if(myBool != YES)ときは、not !演算子を使用する方がずっときれいで、期待どおりの結果が得られます。

1

また、署名付きの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ではなく、signed charである場合、BOOLへの0x0100のキャストは単にセットビットをドロップし、結果の値は0になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.