objective-c에서 YES / NO, TRUE / FALSE와 true / false 사이에 차이가 있습니까?


154

간단한 질문은 정말로; 이 값들 사이에 차이가 있습니까 (그리고 BOOL과 bool 사이에 차이가 있습니까)? 동료는 Objective-C에서 다른 것으로 평가한다고 언급했지만 각각의 .h 파일에서 typedef를 볼 때 YES / TRUE / true는 모두 정의 1되었고 NO / FALSE / false는 모두로 정의되었습니다 0. 실제로 어떤 차이가 있습니까?


5
실제적인 관점에서 차이는 없습니다. 차이를 설명하기 위해 다양한 트릭을 수행 할 수 있지만 일반적으로 "정의되지 않은 동작"영역으로 넘어 가고 있습니다.
핫 릭

답변:


84

실질적인 차이가 없습니다 제공 당신이 사용하는 BOOL논리 값으로 변수. C는 0으로 평가되는지 여부에 따라 부울 표현식을 처리합니다. 따라서 :

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

와 같은 의미

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

그렇기 때문에 모든 기본 유형 또는 표현식을 부울 테스트 (예 : 포인터 포함)로 평가할 수 있습니다. 후자는 아니라 전자를해야합니다.

참고가 있다는 것입니다 당신이 소위에 둔각 값을 할당하면 차이 BOOL때문에 항상 논리 값으로 사용할하고 그들의에서 그들을 지정, 특정 값에 대한 변수 테스트 #define값.

중요한 것은 문자 비교를 사용하여 부울을 테스트하지 마십시오. 예가 someVar아닌 0이 아닌 값을 할당 할 수 있기 때문에 위험 할뿐만 아니라 더 중요한 것은 의도를 올바르게 표현하지 못하는 것입니다.

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

다시 말해, 사용하도록 의도되고 문서화 된 구성을 사용하면 C의 상처를 입은 세상에서 벗어날 수 있습니다.


100

와 사이에 차이 있다고 생각 하는 이유는 다음 웹 페이지에서 확인하십시오. http://iosdevelopertips.com/objective-c/of-bool-and-yes.htmlboolBOOL

프리미티브 유형 BOOL이 아니기 때문에 unsigned char유형의 변수는 및 BOOL이외의 값을 포함 할 수 있습니다 .YESNO

이 코드를 고려하십시오.

BOOL b = 42;

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

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

출력은 다음과 같습니다.

b는 아니요가 아닙니다!
b는 그렇습니다!

대부분의 사람들에게 이것은 불필요한 관심사이지만 실제로 부울을 원한다면을 사용하는 것이 좋습니다 bool. 추가해야합니다 : iOS SDK는 일반적으로 BOOL인터페이스 정의에서 사용하므로 BOOL.


5
그러나 원래 C 구현에는 no가 없었기 bool때문에 int또는 char차이를 숨기려면 때로는 #define과 함께 또는 부울로 사용하는 것이 전통 이었습니다. 사실, 현재 표준조차도 bool내부 구조를 검사하지 못하는 방식으로 구현 해야하는지 확실하지 않습니다 .
핫 릭

1
그러나 첫 번째 printf거짓말은 거짓말입니다. 의 값은 b아닙니다 YES그것은 어떤 조건 시험 인 "제로가 아닌"입니다. 따라서 printf("b is not zero")반드시와 같을 필요는 없습니다 YES. 이 경우 b"0이 아님"및 " 예가 아님"입니다.
Lawrence Dol

감사합니다 로렌스, 나는 그 라인을 따라 업데이트했습니다.
Dan J

실제로, 나는 Xcode 8.2에서 두 번째 출력을 얻지 못했습니다. 내가 어디 실패?
Igor Kislyuk

1
@HotLicks 0과 0이 아닌 0과 0 사이에는 본질적인 차이가 없습니다. 값이 논리 부울로 의도되는 한 이진 호환성을 유지하기 위해 항상이 인터페이스를 갖습니다. 부울처럼 보이는 부울이 아닌 것처럼 사용할 때 문제가 시작됩니다 (예 : c 표준 라이브러리 응용 프로그램 입력 함수, main은 성공시 0을 반환하고 많은 사람들은이 0을 부울로 생각합니다. 실제로 응용 프로그램 정의 열거 또는 사용자 정의 인 경우) 비정상적인 종료시 수신자가 0이 아닌 것으로 예상되는 가치.
Dmitry

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)로 객체 초기화 테스트에 실패합니다. 실제로 제로가 아닌 값이있을 때 단일 "true"값을 정의하는 언어에 익숙하지 않았습니다.
DrFloyd5

3
@SamuelRenkert 나는 if또는 에서 부울이 아닌 값을 취하는 언어에 익숙하지 않았습니다 while. 처럼 ... while("guitar gently weeps")작동하지 않아야합니다 ...
Supuhstar

@SamuelRenkert는 또한 2003 년에 발견 된 Linux 백도어 :if (user_id = ROOT_UID)
Supuhstar

14

질문에 대한 답변을 읽을 수도 있습니다 . 요약하면 오브젝티브 -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

주 (위험!) 차이가 사이 trueYESJSON 직렬화에 있습니다.

예를 들어 JSON 유형의 서버 요청이 있으며 json sence로 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하고 캐스팅 된 값만 JSON 직렬화 로 변환됩니다 . (even ) 과 같은 다른 표현식 은 유형이 있으며 JSON으로 변환됩니다 .@((BOOL)expression)__NSCFBooleantrue@(expression1 && expression2)@(YES && YES)__NSCFNumber (int)1

추신 당신은 단순히 문자열 값 부울을 사용할 수 있습니다

@{@"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 Player

0

나는 그들이 더 많은 설명을 위해 YES / NO를 추가한다고 생각합니다. 예를 들면 다음과 같습니다.

[button setHidden:YES];

보다 나은 소리

[button setHidden:TRUE];

2
동의하지 않습니다. 그들은 둘 다 똑같이 읽습니다. 그러나 평신도의 UI에서는 예 / 아니요가 더 좋아 보인다고 생각합니다.
Lawrence Dol

16
나도 동의하지 않습니다. 다른 언어로 몇 년 동안 사용 된 기록되지 않은 표준을 고수하지 않아서 읽지 못하는 경우가 있습니다. IE는 많은 표준을 준수하지 않을 때 발생하는 주요 예입니다.
FreeAsInBeer

1
2 개의 부정확 한 답변에 대한 반
공감

-2

먼저 참과 거짓이 무엇인지 그리고 무엇을 의미하는지 먼저 살펴 보자.

람다 미적분학에서 if a else 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. ())으로 할 수 있습니다. 우리가 할 수있는 일은 아무것도하지 않고 수행 한 것입니다. 원하는 부작용을 제공하는 시스템)

이것을 실제로 보도록합시다.

(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");})();

배열 / 맵 / 인수 / 또는 둘 이상의 명령문을 사용하여 여러 함수로 나눌 수 있다면 단순화 될 수있는 깊은 환경이지만, 정확히 하나의 인수의 함수로 자신을 제한 할 수있는 한 순수하게 유지하고 싶습니다. 뿐.

True / False라는 이름에는 고유 한 의미가 없으므로 예 / 아니오, 왼쪽 / 오른쪽, 오른쪽 / 왼쪽, 0 / 하나, 사과 / 오렌지로 쉽게 이름을 바꿀 수 있습니다. 어떤 선택을하든 선택 자의 선택에 의해서만 발생한다는 점에서 의미가 있습니다. 따라서 "LEFT"가 인쇄되면 선택자가 사실 일 수 있다는 것을 알고 있으며이 지식을 바탕으로 추가 결정을 안내 할 수 있습니다.

요약하자면

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

아니오, 예 / 아니요는 참 / 거짓 (1/0)을 참조하는 다른 방법입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.