Objective-C: BOOL 与 bool

我看到了“新类型”BOOL (YESNO)。

我读到这种类型几乎类似于char类型。

为了测试,我做了:

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

很高兴看到两个日志都显示“1”(有时在c++中bool是int类型,其sizeof为4)

我想知道bool类型是否有什么问题?

我可以只使用bool(这似乎工作)而不损失速度吗?

197059 次浏览

是的,BOOL是根据objc.h的符号char的类型定义。

但我不了解bool。这是c++的东西,对吧?如果它被定义为一个带符号的字符,其中1是YES/true, 0是NO/false,那么我想使用哪个并不重要。

由于BOOL是Objective-C的一部分,为了清晰起见,使用BOOL可能更有意义(其他Objective-C开发人员如果看到使用BOOL可能会感到困惑)。

你应该使用的Objective-C类型是BOOL。没有任何东西类似于本机布尔数据类型,因此要确保在所有编译器上编译的代码都使用BOOL。(它在Apple-Frameworks中定义。

根据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类型,但所有苹果的Objective-C框架和大多数Objective-C/Cocoa代码都使用BOOL类型,所以如果类型定义发生变化,你可以只使用BOOL类型来避免头痛。

这里我要违背惯例。我不喜欢typedef是基类型。我认为这是一种无用的间接方法,会消除价值。

  1. 当我在你的源代码中看到基本类型时,我会立即理解它。如果它是一个类型定义,我必须查看它,看看我真正在处理什么。
  2. 当移植到另一个编译器或添加另一个库时,它们的typedef集可能会发生冲突,并导致难以调试的问题。事实上,我刚处理完这件事。在一个库中,布尔类型被定义为int型,而在mingw/gcc中,它被定义为char型。

如上所述,BOOL是一个有符号char类型。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");

结果是

< p > < >强真正b1 < br > 真正的b2 < br > NOT REAL b2

注意bool != bool。下面的结果只是再一次-真实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");

所以. .我们现在得到了什么?: -)

bool和bool之间的另一个区别是,当你进行键值观察时,或者当你使用-[NSObject valueForKey:]这样的方法时,它们不会完全转换为相同类型的对象。

大家都说过,BOOL是char类型的。因此,它被转换为一个包含字符的NSNumber。该对象与由' a '或'\0'等常规字符创建的NSNumber无法区分。你完全丢失了你原来拥有的BOOL类型的信息。

然而,bool类型被转换为CFBoolean类型,其行为与NSNumber类型相同,但保留对象的布尔值原点。

我不认为这是BOOL与BOOL的争论,但这可能有一天会咬你一口。

一般来说,你应该选择BOOL类型,因为这是Cocoa/iOS api中随处使用的类型(在C99及其原生BOOL类型之前设计)。

在撰写本文时,这是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");
}

顺便说一句,永远不要将array.count这样的值赋给BOOL变量,因为大约0.4%的可能值将是负数。

接受的答案已被编辑,其解释变得有点不正确。代码示例已刷新,但下面的文本保持不变。现在不能假定BOOL是一个char类型,因为它取决于体系结构和平台。 因此,如果你在32位平台上运行你的代码(例如iPhone 5)并打印@encode(BOOL),你会看到“c”。它对应于char类型。 但如果你在iPhone 5s(64位)上运行你的代码,你会看到“B”。它对应于bool类型。< / p >

如上所述,根据你的体系结构,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当然是不等于等于字符代码1因此if语句将计算为YES/true/1,下面的行将运行。 然而,由于非零bool类型的计算结果总是整数值1,因此上述问题不会影响您的代码。下面是一些好的提示,如果你想使用Objective-C BOOL类型vs ANSI C bool类型:

  • 始终分配YESNO值,而不分配其他值。
  • 使用双not !!操作符转换BOOL类型,以避免意外结果。
  • 在检查YES时使用if(!myBool) instead of if(myBool != YES),使用非!操作符更简洁,并给出预期的结果。

此外,要注意类型转换的差异,特别是在使用位掩码时,由于类型转换为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是有符号char型而不是BOOL型,则将0x0100转换为BOOL型只是丢弃了设置位,结果值为0。