199

我看到了“新类型” BOOLYES, NO)。

我读到这种类型几乎就像一个字符。

为了测试我做了:

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

很高兴看到两个日志都显示“1”(有时在 C++ 中 bool 是一个 int 并且它的 sizeof 是 4)

所以我只是想知道 bool 类型是否有问题?

我可以只使用 bool (这似乎有效)而不会失去速度吗?

4

10 回答 10

206

根据 中的定义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,您将不会感到头疼。

于 2009-02-13T00:43:21.050 回答
35

如上所述,BOOL 是有符号字符。bool - 来自 C99 标准 (int) 的类型。

布尔 - 是/否。布尔 - 真/假。

查看示例:

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

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

于 2011-06-22T09:01:43.600 回答
13

在撰写本文时,这是 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上与在所有其他设备(OS X、32 位 iOS)上BOOL完全一样,它甚至不能被编译器标志覆盖boolsigned 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.countBOOL变量,因为大约 0.4% 的可能值将是负数。

于 2015-10-30T15:24:43.380 回答
8

您应该使用的 Objective-C 类型是BOOL. 没有什么能比得上原生布尔数据类型,因此要确保代码在所有使用BOOL. (它在 Apple 框架中定义。

于 2009-02-12T14:08:32.997 回答
5

是的,BOOL 是根据 objc.h 的有符号字符的 typedef。

不过,我不知道布尔。那是 C++ 的东西,对吧?如果它被定义为一个有符号的字符,其中 1 是 YES/true 而 0 是 NO/false,那么我想你使用哪个并不重要。

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

于 2009-02-12T14:02:00.140 回答
4

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

正如大家在这里所说,BOOL 是字符。因此,它被转换为一个 NSNumber 持有一个字符。该对象与从常规字符(如“A”或“\0”)创建的 NSNumber 无法区分。您已经完全丢失了最初拥有 BOOL 的信息。

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

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

一般来说,您应该使用 BOOL,因为这是 Cocoa/iOS API 中随处使用的类型(在 C99 及其本机 bool 类型之前设计)。

于 2012-05-08T08:12:46.723 回答
2

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

于 2016-02-13T13:20:10.657 回答
2

如上所述,取决于您的架构,它BOOL可能是一种类型,而类型是. 一个简单的实验将展示 BOOL 和 bool 行为不同的原因:unsigned charboolint

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类型与ANSI C bool类型,以下是一些很好的提示:

  • 始终分配YESorNO值,仅此而已。
  • BOOL使用 double not运算符转换类型!!以避免意外结果。
  • 在检查YES使用if(!myBool) instead of if(myBool != YES)时,使用 not 运算符会更干净,!并给出预期的结果。
于 2017-12-11T22:51:26.550 回答
1

我在这里违反惯例。我不喜欢 typedef 的基本类型。我认为这是一个无用的间接删除价值。

  1. 当我在您的源代码中看到基本类型时,我会立即理解它。如果它是 typedef,我必须查找它以查看我真正处理的内容。
  2. 当移植到另一个编译器或添加另一个库时,它们的 typedef 集可能会发生冲突并导致难以调试的问题。事实上,我刚刚处理完这个问题。在一个库中,布尔值被定义为 int,而在 mingw/gcc 中,它被定义为字符。
于 2010-04-05T17:15:51.347 回答
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。

于 2019-08-29T20:29:21.280 回答