오브젝티브 -C : BOOL vs Bool


192

"신형" BOOL( YES, NO)을 보았습니다 .

나는이 유형이 거의 문자와 같다는 것을 읽었습니다.

테스트를 위해 나는 :

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

두 로그 모두에 "1"이 표시되는 것을 확인하는 것이 좋습니다 (때로는 C ++ bool은 int이고 sizeof는 4 임).

그래서 부울 유형이나 무언가에 문제가 있는지 궁금합니다.

속도를 잃지 않고 부울을 사용할 수 있습니까?

답변:


199

의 정의에서 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이 문자라고 가정 할 수 있습니다. (C99) bool유형을 사용할 수 있지만 모든 Apple Objective-C 프레임 워크 및 대부분의 Objective-C / Cocoa 코드는 BOOL을 사용하므로 BOOL을 사용하여 typedef가 변경되면 두통을 피할 수 있습니다.


17
"모든 Apple의 프레임 워크"-사실이 아닙니다. 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

@ Cœur BOOL 코드 샘플의 정의를 편집했지만 아래 텍스트는 동일하게 유지됩니다. 약간 혼란스럽고 잘못되었습니다. 내 대답을 참조하십시오.
호기심

다른 행동을 아래에서 살펴보십시오. NSInteger progressTime = 2;//any value NSInteger totalTime = 1;//any value BOOL success = (progressTime>=totalTime)// 항상 제공 NO 하지만 해당 (progressTime>=totalTime)값을 bool유형 으로 받으면 success올바른 결과를 반환합니다. 나는이 행동을 이해하지 못한다. 사용 Xcode 7.x하고 있으며 iOS버전은 8.x입니다. @BarryWark
Kamar Shad

34

위에서 언급했듯이 BOOL은 부호가있는 문자입니다. bool-C99 표준 (int)의 유형입니다.

BOOL-예 / 아니요. 부울-참 / 거짓.

예를보십시오 :

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
실제 b2 실제 b2
아님

bool! = BOOL입니다. 아래 결과는 ONCE AGAIN-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
삼항 연산자 use 대신을 사용할 수 있습니다 !!b1. 그들 사이에 변환
Richard J. Ross III

1
iPhone SE 시뮬레이터에 'NOT REAL b2'가 인쇄되지 않습니다.
gabbler

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

BTW 는 가능한 값의 약 0.4 %가 음수가되기 때문에 변수 와 같은 array.count것을 할당하지 않습니다 BOOL.


iOS 32 비트 (iPhone 5C ...)를 컴파일 할 때 BOOL (UIView 애니메이션 블록 등)을 얻기 위해 정의 된 블록의 매개 변수로 bool을 사용하면 컴파일러에서 오류가 발생합니다. 코드의 어느 곳에서나 C ++ bool을 사용하고 BOOL로 정의 된 API에서 BOOL
stephane k를 사용합니다.

8

사용해야하는 Objective-C 유형은 BOOL입니다. 기본 부울 데이터 유형과 같은 것은 없으므로 모든 컴파일러에서 코드를 컴파일 할 때 사용하십시오 BOOL. (Apple-Frameworks에 정의되어 있습니다.


2
이것은 정확히 정확하지 않습니다. 프레임 워크가 아닌 BOOLObjective-C 언어 ( objc/*.h헤더 중 하나에 있음)로 정의됩니다 . 또한 C99로 컴파일 할 때 (기본이라고 생각합니다) 기본 부울 유형이 있습니다 _Bool(또는 포함 된 bool경우 stdbool.h).
dreamlax

5

예, BOOL은 objc.h에 따르면 서명 된 문자의 typedef입니다.

그래도 bool에 대해서는 모른다. 그것은 C ++ 일입니까? 1이 YES / true이고 0이 NO / false 인 부호있는 문자로 정의 된 경우 어떤 문자를 사용하든 상관 없습니다.

그러나 BOOL은 Objective-C의 일부이므로 명확성을 위해 BOOL을 사용하는 것이 더 합리적입니다.


6
_Bool은 C99에 정의되어 있으며 표준 헤더 stdbool.h에 매크로 bool이 정의되고 (_Bool로 확장 됨) true / false도 여기에 정의됩니다.
Brian Mitchell

4

bool과 BOOL의 또 다른 차이점은 키-값 관찰을 수행하거나-[NSObject valueForKey :]와 같은 메소드를 사용할 때 동일한 종류의 객체로 정확하게 변환되지 않는다는 것입니다.

모두가 여기에서 말했듯이 BOOL은 char입니다. 따라서 char를 보유한 NSNumber로 변환됩니다. 이 개체는 'A'또는 '\ 0'과 같은 일반 문자로 만든 NSNumber와 구별 할 수 없습니다. 당신은 당신이 원래 BOOL을 가지고 있었던 정보를 완전히 잃어 버렸습니다.

그러나 bool은 CFNumber로 변환되어 NSNumber와 동일하게 동작하지만 오브젝트의 부울 원점은 유지합니다.

나는 이것이 BOOL vs. bool 토론에서 논쟁이라고 생각하지 않지만 이것은 언젠가 물릴 수 있습니다.

Cocoa / iOS API (C99 이전에 설계된 기본 bool 유형)에서 사용되는 유형이므로 일반적으로 BOOL을 사용해야합니다.


2

수락 된 답변이 수정되었으며 설명이 약간 잘못되었습니다. 코드 샘플이 새로 고쳐졌지만 아래 텍스트는 동일하게 유지됩니다. BOOL은 아키텍처와 플랫폼에 따라 다르므로 현재로서는 문자라고 가정 할 수 없습니다. 따라서 32 비트 플랫폼 (예 : iPhone 5)에서 코드를 실행하고 @encode (BOOL)를 인쇄하면 "c"가 표시됩니다. char 타입에 해당 합니다 . 그러나 iPhone 5s (64 비트)에서 코드를 실행하면 "B"가 표시됩니다. 부울 유형에 해당 합니다 .


1

나는 여기서 대회에 반대한다. 나는 typedef를 기본 유형에 좋아하지 않습니다. 나는 그것이 가치를 제거하는 쓸모없는 간접적이라고 생각합니다.

  1. 소스에서 기본 유형을 보면 즉시 이해할 수 있습니다. 그것이 typedef라면 내가 실제로 다루고있는 것을보기 위해 그것을 찾아야합니다.
  2. 다른 컴파일러로 포팅하거나 다른 라이브러리를 추가 할 때 typedef 세트가 충돌하여 디버깅하기 어려운 문제가 발생할 수 있습니다. 나는 실제로 이것을 다루었습니다. 하나의 라이브러리에서 부울은 int로 typedef되었고, mingw / gcc에서는 char로 typedef되었습니다.

4
음 ... 당신은 할 수 있습니다 표준 타입 정의 언어 (생각의 알고 것으로 예상 size_t), 두 bool(C99) 및 BOOL그 카테고리에 (ObjC) 가을. 그리고 typedef의 변경으로 인해 코드가 실패한 경우 typedef를 불투명 한 것으로 취급하지 않았지만 하나의 플랫폼에서의 구현에 의존했기 때문에 코드가 책임이 있습니다. (부끄러워 할 것은 없지만, 그렇게하는 것은 typedef가 아닙니다.)
DevSolar

1
"표준"typedef는 매우 표준적인 것처럼 보이지 않습니다 (예를 들어, MS가 posix 표준 등을 지원하지 않는 동안). typedef를 사용하지 않으면 다른 컴파일러에서 typedef가 변경되거나 다른 문제가 제거됩니다.
Jay

1
-1, typedef는 일반적으로 두 가지 중요한 목적 (다른 의미 중에서도)을 제공합니다. 좋은 의미를 제공하고 약간의 방향을 제시하십시오. 이상적으로 typedef가 참조하는 기본 유형을 알 필요는 없습니다. 불행히도이 시스템은 완벽하지 않으며 때로는 알아야합니다. 내 요점은 : 당신은 그것의 대안보다 완벽하지 않다는 것을 인정하기 때문에 대회를 따라야합니다.
João Portela

2
@Jay : 죄송합니다. 왜 "misdirection"이 좋은지 설명해야합니다. 예제를 제공하려고합니다. int 또는 char을 직접 사용하는 대신 typedef'd boolean을 사용하는 경우 코드를 손상시키지 않고 각 플랫폼에서 다른 유형 (아직 작동하는)을 사용할 수 있습니다. 이것은 다양하지만 char에서 메모리에 정렬이 잘못되어 플랫폼이 부울에 대신 int를 사용할 수있는 플랫폼을 상상할 수 있습니다.
João Portela

2
@Jay : "좋은 의미"으로는 내 말은 당신이 당신의 부울을 선언 할 때 BOOL varname대신 char varname이 그 변수에 대한 두 개의 유효한 값이라는 것을 더 분명하다 true/ YESfalse/ NO.
João Portela

1

위에서 언급했듯이 아키텍처에 따라 유형 BOOL이 될 수 있지만 unsigned char유형 bool은입니다 int. 간단한 실험은 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);

놀랍게도 실제로 문자 코드 1 if(objcBOOL != YES)이므로 컴파일러가 1로 평가합니다. 컴파일러 YES의 눈에는 문자 코드 64가 문자 코드 1 과 동일하지 않으므로 if 문이 평가되고 YES/true/1다음 줄은 운영. 그러나 none zero bool유형은 항상 정수 값 1로 평가되므로 위의 문제는 코드에 영향을 미치지 않습니다. 다음은 Objective-C BOOLtype과 type 을 사용하려는 경우 유용한 팁입니다 ANSI C bool.

  • 항상 YES또는 NO값을 지정하고 다른 것은 지정 하지 마십시오.
  • 예기치 않은 결과를 피하기 위해 BOOLdouble not !!연산자를 사용하여 유형을 변환하십시오 .
  • YES사용을 점검 할 때 if(!myBool) instead of if(myBool != YES)not !연산자 를 사용 하는 것이 훨씬 깨끗 하며 예상 된 결과를 제공합니다.

1

또한 서명 된 문자로 캐스트하기 때문에 특히 비트 마스크로 작업 할 때 캐스트의 차이점에 유의하십시오.

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이 부울 대신 부호있는 문자 인 경우 0x0100을 BOOL로 캐스트하면 단순히 설정된 비트가 삭제되고 결과 값은 0입니다.

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