Objective-C : BOOL vs bool
我看到了"新类型"
我读到这种类型几乎就像一个字母。
为了测试,我做了:
1 2 | NSLog(@"Size of BOOL %d", sizeof(BOOL)); NSLog(@"Size of bool %d", sizeof(bool)); |
很高兴看到两个日志都显示"1"(有时在C ++中bool是一个int,其sizeof是4)
所以我只是想知道bool类型是否存在某些问题?
我可以在不失速度的情况下使用bool(看似有效)吗?
从
1 2 3 4 5 6 7 8 9 10 | #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是一个签名字符。 bool - 来自C99标准(int)的类型。
BOOL - 是/否。 bool - 真/假。
见例子:
1 2 3 4 5 6 7 8 9 10 11 |
结果是
REAL b1
REAL b2
NOT REAL b2
注意bool!= BOOL。以下结果仅为ONCE AGAIN - REAL b2
1 2 3 4 5 |
如果你想将bool转换为BOOL,你应该使用下一个代码
1 | BOOL b22 = b1 ? YES : NO; //and back - bool b11 = b2 ? true : false; |
所以,在我们的案例中:
1 2 3 4 5 |
那么......我们现在得到了什么? :-)
在撰写本文时,这是objc.h的最新版本:
1 2 3 4 5 6 7 8 9 10 | /// 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
它还意味着此示例代码将在不同平台上以不同方式运行(我自己测试):
1 2 3 4 5 6 7 |
BTW从不将
您应该使用的Objective-C类型是
根据objc.h,Yup,BOOL是签名字符的typedef.
不过我不知道bool。这是C ++的事情,对吧?如果它被定义为一个有符号的字符,其中1是YES / true而0是NO / false,那么我想你使用哪一个并不重要。
但是,由于BOOL是Objective-C的一部分,因此为了清晰起见使用BOOL可能更有意义(如果他们看到使用bool,其他Objective-C开发人员可能会感到困惑)。
bool和BOOL之间的另一个区别是,当您进行键值观察时,或者使用类似 - [NSObject valueForKey:]的方法时,它们不会完全转换为相同类型的对象。
正如大家在这里所说,BOOL是char。因此,它被转换为持有char的NSNumber。此对象与从常规字符"A"或" 0"创建的NSNumber无法区分。您完全丢失了原本拥有BOOL的信息。
但是,bool被转换为CFBoolean,其行为与NSNumber相同,但保留了对象的布尔原点。
我认为这不是BOOL与bool辩论中的争论,但有一天这可能会让你感到厌烦。
一般来说,你应该使用BOOL,因为这是Cocoa / iOS API中所使用的类型(在C99及其原生bool类型之前设计)。
已接受的答案已被编辑,其解释变得有点不正确。代码示例已刷新,但下面的文本保持不变。你不能认为BOOL现在是一个char,因为它依赖于架构和平台。
因此,如果您在32位平台(例如iPhone 5)上运行代码并打印@encode(BOOL),您将看到"c"。它对应于char类型。
但如果你在iPhone 5s(64位)上运行代码,你会看到"B"。它对应于bool类型。
如上所述,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | bool ansicBool = 64; if(ansicBool != true) printf("This will not print "); printf("Any given vlaue other than 0 to ansicBool is evaluated to %i ", ansicBool); BOOL objcBOOL = 64; if(objcBOOL != YES) printf("This might print depnding on your architecture "); printf("BOOL will keep whatever value you assign it: %i ", objcBOOL); if(!objcBOOL) printf("This will not print "); printf("! operator will zero objcBOOL %i ", !objcBOOL); if(!!objcBOOL) printf("!! will evaluate objcBOOL value to %i ", !!objcBOOL); |
令你惊讶的是,
但是,由于非零
-
始终指定
YES 或NO 值,而不是其他任何内容。 -
使用double not
!! 运算符转换BOOL 类型以避免意外结果。 -
检查
YES 时使用if(!myBool) instead of if(myBool != YES) ,使用not! 运算符并提供预期结果会更清晰。
我在这里反对惯例。我不喜欢typedef的基类型。我认为这是一种无用的间接方式,可以消除价值。
此外,请注意转换中的差异,特别是在使用位掩码时,由于转换为signed char:
1 2 3 4 5 6 | 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。