Objective-CのYES / NO、TRUE / FALSEとtrue / falseに違いはありますか?


154

本当に簡単な質問です。これらの値に違いはありますか(BOOLとboolには違いがありますか)?同僚はObjective-Cでさまざまなことを評価すると述べましたが、それぞれの.hファイルのtypedefを見ると、YES / TRUE / trueはすべてとして定義されて1おり、NO / FALSE / falseはすべてとして定義されてい0ます。本当に違いはありますか?


5
実用的な観点からは違いはありません。おそらく、さまざまなトリックを実行して違いを示すことができますが、通常は「未定義の動作」の領域に迷い込んでいます。
Hot Licks 2012年

回答:


84

実用的な違いはありませんあなたが使用BOOLブール値として変数を。Cは、評価が0か0でないかに基づいてブール式を処理します。

if(someVar ) { ... }
if(!someVar) { ... }

と同じ意味

if(someVar!=0) { ... }
if(someVar==0) { ... }

これが、プリミティブ型または式をブールテスト(ポインタなど)として評価できる理由です。後者ではなく前者を実行する必要があることに注意してください。

あいまいな値をいわゆる変数に割り当てて特定の値をテストする場合違いあることに注意してください。BOOL常にブール値として使用し、それらの#define値からのみ割り当ててください。

重要なのは、文字比較を使用してブール値をテストしないことsomeVarです。これは、YESではないゼロ以外の値が割り当てられる可能性があるため、リスクがあるだけでなく、私の考えでは、意図を正しく表現できません。

if(someVar==YES) { ... } // don't do this!
if(someVar==NO ) { ... } // don't do this either!

言い換えれば、使用するために意図され、文書化されているように構成体を使用すれば、Cの傷ついた世界から身を守ることができます。


100

私は信じているとの違いboolとはBOOL:理由の説明のために、このWebページをチェックアウトし、
http://iosdevelopertips.com/objective-c/of-bool-and-yes.html

BOOLunsigned charプリミティブ型ではなくであるため、型の変数にBOOLYESおよび以外の値を含めることができますNO

このコードを考えてみましょう:

BOOL b = 42;

if (b) {
    printf("b is not NO!\n");
}

if (b != YES) {
    printf("b is not YES!\n");
}

出力は次のとおりです。

bはNOではありません!
bはYESではありません!

ほとんどの人にとってこれは不必要な懸念事項ですが、本当にブール値が必要な場合はを使用することをお勧めしますbool。追加する必要があります:iOS SDKは通常BOOL、インターフェイス定義で使用するため、これはに固執するための引数BOOLです。


5
ただし、元のCの実装にはがなかっboolたため、intまたはcharをブール値として使用するのが伝統であり、場合によっては#defineを使用して違いを隠すこともしないこともあります。実際、現在の標準でさえbool、内部構造の調査を妨げる方法で実装する必要があるかどうかはわかりません。
Hot Licks 2012年

1
しかし、最初printfは嘘をつきます。の値はbでなくYES、「ゼロでない」であり、これは条件がテストするものです。つまりprintf("b is not zero")、と同じである必要はありませんYES。この場合、bは「ゼロではない」と「YESではない」の両方です。
Lawrence Dol 2014

ローレンスのおかげで、私はそれらの線に沿って更新を行いました。
Dan J

確かに、Xcode 8.2では2番目の出力を取得できませんでした。どこで失敗するの?
Igor Kislyuk 2017

1
@HotLicks 0ではなく、falseとtrueの間に固有の違いはありません。値が論理ブールであることを意図している限り、バイナリ互換性を維持するために、常にこのインターフェイスが含まれます。ブールのように見える非ブールを使用すると、問題が始まります。たとえば、標準ライブラリアプリケーションのエントリ関数では、mainは成功時に0を返し、実際にはアプリケーション定義の列挙型またはユーザー定義のときに、この0をブール値と見なしてしまいます。呼び出し先は、異常終了時にゼロ以外であると予期することが多い値。
ドミトリー

52

私はこれについて徹底的なテストを行いました。私の結果はそれ自体が物語っています:

//These will all print "1"
NSLog(@"%d", true == true);
NSLog(@"%d", TRUE == true);
NSLog(@"%d", YES  == true);
NSLog(@"%d", true == TRUE);
NSLog(@"%d", TRUE == TRUE);
NSLog(@"%d", YES  == TRUE);
NSLog(@"%d", true == YES);
NSLog(@"%d", TRUE == YES);
NSLog(@"%d", YES  == YES);

NSLog(@"%d", false == false);
NSLog(@"%d", FALSE == false);
NSLog(@"%d", NO    == false);
NSLog(@"%d", false == FALSE);
NSLog(@"%d", FALSE == FALSE);
NSLog(@"%d", NO    == FALSE);
NSLog(@"%d", false == NO);
NSLog(@"%d", FALSE == NO);
NSLog(@"%d", NO    == NO);


//These will all print "0"
NSLog(@"%d", false == true);
NSLog(@"%d", FALSE == true);
NSLog(@"%d", NO    == true);
NSLog(@"%d", false == TRUE);
NSLog(@"%d", FALSE == TRUE);
NSLog(@"%d", NO    == TRUE);
NSLog(@"%d", false == YES);
NSLog(@"%d", FALSE == YES);
NSLog(@"%d", NO    == YES);

NSLog(@"%d", true == false);
NSLog(@"%d", TRUE == false);
NSLog(@"%d", YES  == false);
NSLog(@"%d", true == FALSE);
NSLog(@"%d", TRUE == FALSE);
NSLog(@"%d", YES  == FALSE);
NSLog(@"%d", true == NO);
NSLog(@"%d", TRUE == NO);
NSLog(@"%d", YES  == NO);

出力は次のとおりです。

2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.072 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.076 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.082 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.091 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.092 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.097 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.098 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.101 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0

3
[[NSObject] alloc] init]がTRUEまたはYESと等しくない。したがって、if([[NSObject] alloc] init] == TRUE)を使用したオブジェクト初期化のテストは失敗します。ゼロ以外の値で実際に機能する場合でも、単一の「真」の値を定義する言語に慣れていません。
DrFloyd5 2013

3
@SamuelRenkert ifまたはでブール値以外の値をとる言語に慣れていませんwhile。のような...動作しwhile("guitar gently weeps")ないはずです...
Supuhstar

@SamuelRenkertまた、2003年に発見されたのLinuxバックドア:if (user_id = ROOT_UID)
Supuhstar

14

この質問への回答を読んでください。要約すると、Objective-Cでは(objc.hの定義から):

typedef signed char        BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used.
#define OBJC_BOOL_DEFINED


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

11

間の主な(危険!)の違いtrueとは、YESJSONのシリアル化です。

たとえば、JSONタイプのサーバーリクエストがあり、jsonの意味でtrue / falseを送信する必要があります。

NSDictionary *r1 = @{@"bool" : @(true)};
NSDictionary *r2 = @{@"bool" : @(YES)};
NSDictionary *r3 = @{@"bool" : @((BOOL)true)};

次に、JSON文字列に変換してから送信します

NSData *data = [NSJSONSerialization  dataWithJSONObject:requestParams options:0 error:nil];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

結果は

jsonString1 // {"bool":1}
jsonString2 // {"bool":true}
jsonString3 // {"bool":true}

APIロジックによりjsonString1、エラーが発生する可能性があります。

したがって、Objective-Cのブール値には注意してください。

唯一の正確な、要約する@YESと鋳造値として@((BOOL)expression)のものである__NSCFBooleanタイプとに変換trueJSONシリアライゼーションと。@(expression1 && expression2)(even @(YES && YES))などの他の式はすべて__NSCFNumber (int)タイプであり1、JSONに変換されます。

PSあなたは単に文字列値のブール値を使用することができます

@{@"bool" : @"true"}; // in JSON {"bool":true}

1

ここには誰も言及していない微妙なバグがあり、私は含めたいと思っていました...何よりも論理的なエラーです:

int i = 2;
if(i);        //true
if(i==YES);   // false
if((!!i)==YES); //true

したがって、ここでの問題はそれだけで(YES==1)あり、Cでの比較はブール値ではなく、値に基づく比較です。

ためYESだけである#define(むしろ言語に固有のものよりも)、それはいくつかの値である必要があり、そして1最も理にかなっています。


これは本質的に、2年以上前のDanJの回答と同じですが、詳細はあまりありません。
Lawrence Dol

@LawrenceDolわかりません、それはYESが1に定義されているだけで、言語に固有ではないことを示しています。それは、より高いレベルの言語のように...誰かがそれから価値を得る可能性があります...しかし、良いトローリング。
Gradyプレーヤー、

0

多くの場合、彼らはYES / NOを追加することでより自明になると思います。例えば:

[button setHidden:YES];

よりよく聞こえる

[button setHidden:TRUE];

2
同意しません; どちらも同じように読んでいます。ただし、素人のUIでは、はい/いいえの方が見栄えが良いと思います。
ローレンスドル

16
私も同意しません。どちらかといえば、長年他の言語で使用されてきた未記述の標準に固執しないため、読みにくくなります。IEは、多数の標準に準拠していない場合に何が起こるかを示す代表的な例です。
FreeAsInBeer

1
2つの不正確な回答に対する反対投票と回答
反対投票

-2

最初に、真と偽とは何か、そしてそもそもそれらが何を意味するのかを調べてみましょう。

次のようにラムダ計算でif a then b else cという構造を作成できます。

(\ifThenElse. <use if then else>)(\a. \b. \c. a b c)

JavaScriptでは、これは次のようになります。

(function(ifThenElse) {
    // use ifThenElse
})(function(a) {
    return function(b) {
        return function(c) {
            return a(b)(c);
        };
    };
});

ifThenElseを使用するには、右または左を選択し、他のオプションを無視してそれを行う関数「true」が必要です。または、オプション「true」を選択する関数「false」は使用しません。

これらの関数は次のように定義できます。

(\true. <use true>)(\a. \b. a) and (\false. <use false>)(\a. \b. b)

JavaScriptでは次のようになります。

(function(True) {
    // use True
})(function(a) {
     return function(b) {
         return a;
     }
});

(function(False) {
    // use True
})(function(a) {
     return function(b) {
         return b;
     }
});

今、私たちは次のことができます

(\true. \false. \ifThenElse. \doThis. \doThat. ifThenElse true doThis doThat)
(\a. \b. a)(\a. \b. b)(\a. \b. \c. a b c)(\a. ())(\a. ())

doThisとdoThatが(\ a。())であるので、ラムダ計算はprint / math / stringsなどのサービスを提供していないため、何もせずにそれを行ったと言うだけで済みます(後でそれを私たちが望む副作用を提供する私たちのシステム)

これを実際に見てみましょう。

(function(True) {
    return (function(False) {
        return (function(ifThenElse) {
            return (function(doThis) {
                return (function(doThat) {
                    return ifThenElse(True)(doThis)(doThat);
                });
            });
        });
    })
})(function(a) {
     return function(b) {
         return a;
     }
})(function(a) {
     return function(b) {
         return b;
     }
})(function(a) {
    return function(b) {
        return function(c) {
            return a(b)(c);
        };
    };
})(function(a) { console.log("you chose LEFT!"); })
(function(a) {console.log("you chose RIGHT");})();

これは、配列/マップ/引数/または複数の関数に分割するために複数のステートメントを使用することが許可されている場合に簡略化できる深い環境ですが、保持したいのは、引数を1つだけの関数に制限することです。のみ。

True / Falseという名前には固有の意味がないことに注意してください。名前を簡単にyes / no、left / right、right / left、zero / one、apple / orangeに変更できます。それはどんな選択がなされても、それはそれを作った選択者の種類によってのみ引き起こされるという意味で重要です。したがって、「LEFT」が印刷されている場合、セレクターはtrueである可能性があることがわかります。この知識に基づいて、さらに決定を下すことができます。

要約すると

function ChooseRight(left) {
    return function _ChooseRight_inner(right) {
        return right;
    }
}
function ChooseLeft(left) {
    return function _ChooseLeft_inner(right) {
        return left;
    }
}

var env = {
    '0': ChooseLeft,
    '1': ChooseRight,
    'false': ChooseRight,
    'true': ChooseLeft,
    'no': ChooseRight
    'yes': ChooseLeft,
    'snd': ChooseRight,
    'fst': ChooseLeft
};
var _0 = env['0'];
var _1 = env['1'];
var _true = env['true'];
var _false = env['false'];
var yes = env['yes'];
var no = env['no'];

// encodes church zero or one to boolean
function lambda_encodeBoolean(self) {
    return self(false)(true);
}
// decodes a Boolean to church zero or one
function lambda_decodeBoolean(self) {
    console.log(self, self ? env['true'] : env['false']);
    return self ? env['true'] : env['false'];
}

lambda_decodeBoolean('one' === 'two')(function() {
    console.log('one is two');
})(function() {
    console.log('one is not two');
})();

lambda_decodeBoolean('one' === 'one')(function() {
    console.log('one is one');
})(function() {
    console.log('one is not one');
})();

-7

いいえ、YES / NOはTRUE / FALSE(1/0)を参照する別の方法です

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