Objective-C:布尔与布尔


192

我看到了“新类型” BOOLYESNO)。

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

为了测试,我做了:

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

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

所以我只是想知道布尔类型是否有问题或什么?

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

Answers:


198

从中的定义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
“苹果的所有框架”-不是这样。看一下CGGeometry.h,特别是:CG_INLINE bool __CGPointEqualToPoint(CGPoint point1,CGPoint point2){return point1.x == point2.x && point1.y == point2.y; }
Elliot

58
@艾略特你是正确的。许多C框架(CoreFoundation,CoreGraphics等)都使用C99 bool。所有的Objective-C框架都使用BOOL
巴里·沃克

@Cœur您已经编辑了BOOL代码示例的定义,但是下面的文本保持不变。这有点令人困惑并且不正确。看我的答案。
好奇

要了解不同的行为,请看下面的内容。 NSInteger progressTime = 2;//any value NSInteger totalTime = 1;//any value BOOL success = (progressTime>=totalTime)//它总是给定的,NO 但是一旦我收到该 类型的(progressTime>=totalTime)值,它就会返回正确的结果。我不了解这种行为。我正在使用,版本为。@BarryWarkboolsuccessXcode 7.xiOS8.x
Kamar Shad

34

如上所述,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。以下结果仅一次-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。在他们之间转换
理查德·罗斯三世

1
我的iPhone SE模拟器上未打印“ NOT REAL b2”。
gabbler'1

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 BOOL上,它与bool在所有其他设备(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从未分配的东西喜欢array.countBOOL的变量,因为约0.4可能值%将是负面的。


如果为iOS 32位(iPhone 5C ...)编译时,如果将bool用作定义为获取BOOL的块的参数(例如,UIView动画块),则编译器将引发错误。我在代码中到处都使用C ++ bool,在用BOOL定义的API
stephane k)中

8

您应该使用的Objective-C类型是BOOL。没有像本地布尔数据类型那样的东西,因此请确保所有编译器使用编译代码BOOL。(在Apple-Frameworks中定义。


2
这不是严格准确的。BOOL由Objective-C语言定义(在objc/*.h标题之一中),而不是由框架定义。另外,当使用C99(我认为是默认值)进行编译时,则存在本机布尔类型_Bool(或bool如果stdbool.h包含)。
dreamlax

5

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

我不知道布尔。那是C ++的事情,对不对?如果将其定义为带符号的char,其中1是YES / true,0是NO / false,那么我认为使用哪一个都没有关系。

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


6
_Bool在C99中定义,并且在标准头文件stdbool.h中,定义了宏bool(扩展为_Bool),在此也定义了true / false。
Brian Mitchell

4

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

就像大家在这里所说的,BOOL是char。这样,它将转换为包含字符的NSNumber。该对象与由常规字符(如“ A”或“ \ 0”)创建的NSNumber不可区分。您已经完全失去了最初拥有BOOL的信息。

但是,布尔值将转换为CFBoolean,其行为与NSNumber相同,但保留了对象的布尔源。

我不认为这是BOOL与bool辩论中的论点,但这可能有一天会困扰您。

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


2

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


1

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

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

4
嗯......你可以期望知道标准的typedef是你的语言(想size_t),和两个bool(C99)和BOOL(ObjC)属于这一类。而且,如果您的代码由于typedef的更改而失败,则应该归咎于您的代码,因为您显然不是将typedef视为不透明的东西,而是依赖于在一个平台上的实现。(它不会让您感到羞耻,但是,这并不是应该责怪的typedef。)
DevSolar 2010年

1
“标准” typedef似乎不是很标准(例如,一段时间以来,MS不支持posix标准,等等)。如果不使用typedef,则可以消除在不同的编译器上typedef更改或不同的问题。
杰伊

1
-1,typedef通常具有两个重要目的(除其他外):提供良好的语义并提供一些误导。理想情况下,您不需要知道typedef所引用的基本类型,不幸的是,该系统不是完美的,有时您必须知道。我的观点是:您应该遵循约定,因为即使承认它并不完美,也比替代方案更好。
若昂里斯本

2
@杰伊:对不起,我应该解释为什么这种“误导”是好的。我将尝试提供一个示例:如果您使用typedef的boolean而不是直接使用int或char,那么您将允许在每个平台上使用其他类型(仍然有效)而不破坏代码[原因这有所不同,但是我们可以想象一个平台,其中的char可能在内存中未对齐,从而变慢,因此可以将int用作布尔值]。
若昂里斯本

2
@Jay:“良好的语义”是指在声明布尔值BOOL varname而不是布尔char varname值时,该变量的两个有效值为true/ YESfalse/ 更为明显NO
若昂里斯本

1

如上所述,取决于您的体系结构,BOOL可以是unsigned chartype,而booltype是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);

令您惊讶的if(objcBOOL != YES)是,编译器将其计算为1,因为YES实际上它是字符代码1,并且在编译器看来,字符代码64当然不等于字符代码1,因此if语句的计算结果为YES/true/1,而下一行将跑。但是,由于非零bool类型始终求值为1的整数,因此上述问题不会影响您的代码。如果您想使用Objective-C BOOL类型与ANSI C bool类型,以下是一些很好的技巧:

  • 始终分配YESNO值,而别无其他。
  • BOOL通过使用double not !!运算符转换类型,以避免出现意外结果。
  • 在检查YES使用if(!myBool) instead of if(myBool != YES)情况时,使用not !运算符会更清洁,并给出预期的结果。

1

另外,请注意转换的不同,尤其是在使用位掩码时,由于转换为带符号的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。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.