在iOS上使用64位BOOL

wei*_*ang 49 objective-c ios

当我BOOL用于32位时,我得到:

BOOL b1=8960; //b1 == NO

bool b2=8960; //b2 == true  
Run Code Online (Sandbox Code Playgroud)

但对于64位,我得到:

BOOL b1=8960; //b1 == YES

bool b2=8960; //b2 == true
Run Code Online (Sandbox Code Playgroud)

发生了什么变化大约BOOL从32位到64位?

zrz*_*zka 89

@TimBodeit是对的,但它没有解释为什么......

BOOL b1=8960; //b1 == NO
Run Code Online (Sandbox Code Playgroud)

...评估NO在32位iOS上以及为什么它YES在64位iOS上进行评估.让我们从同一个开始.

ObjC BOOL定义

#if (TARGET_OS_IPHONE && __LP64__)  ||  (__ARM_ARCH_7K__ >= 2)
#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
Run Code Online (Sandbox Code Playgroud)

对于64位iOS或ARMv7k(手表),它被定义为bool,其余为signed char.

ObjC BOOL是和否

阅读Objective-C Literals,您可以在其中找到:

以前,BOOL类型只是一个typedef signed char, YES并且NO是 分别扩展为(BOOL)1和的宏(BOOL)0.为了支持@YES@NO表达式,现在使用新语言关键字定义这些宏<objc/objc.h>:

#if __has_feature(objc_bool)
#define YES __objc_yes
#define NO  __objc_no
#else
#define YES ((BOOL)1)
#define NO  ((BOOL)0)
#endif
Run Code Online (Sandbox Code Playgroud)

编译器隐式转换__objc_yes,并__objc_no(BOOL)1(BOOL)0.关键字用于消除BOOL和整数文字的歧义.

布尔定义

bool是一个定义的宏stdbool.h,它扩展为_Bool,这是C99中引入的布尔类型.它可以存储两个值,01.没有其他的.更准确地说,stdbool.h定义了四个要使用的宏:

/* Don't define bool, true, and false in C++, except as a GNU extension. */
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
/* Define _Bool, bool, false, true as a GNU extension. */
#define _Bool bool
#define bool  bool
#define false false
#define true  true
#endif

#define __bool_true_false_are_defined 1
Run Code Online (Sandbox Code Playgroud)

_Bool

_Bool是在C99中引入的,它可以保存值01.重要的是:

当值降级为a时_Bool,结果是0值等于0,1否则.

现在我们知道这个混乱的来源,我们可以更好地了解正在发生的事情.

64位iOS || ARMv7k

BOOL- > bool- > _Bool(值01)

降级8960_Bool1,因为值不等于0.见(_Bool部分).

32位iOS

BOOL- > signed char(值-128127).

如果您要将int值(-128to 127)存储为signed char,则每个C99 6.3.1.3的值不变.否则它是实现定义的(C99引用):

否则,新类型将被签名,并且值无法在其中表示; 结果是实现定义的,或者引发实现定义的信号.

这意味着clang可以决定.为了简化,使用默认设置,clang将其包裹起来(int- > signed char):

  • -129成了127,
  • -130成了126,
  • -131成了125,
  • ...

而在相反的方向:

  • 128成了-128,
  • 129成了-127,
  • 130成了-126,
  • ...

但由于signed char可以存储值的范围-128127,它可以存储0为好.例如256(int)变为0(signed char).当你的价值8960被包裹起来......

  • 8960成了0,
  • 8961成了1,
  • 8959成了-1,
  • ...

...就变成0存储在时signed char(8960是的倍数256,8960 % 256 == 0),因而它的NO.这同样适用于256,512中,...倍数256.

我强烈建议使用YES,NOBOOL和不依赖于花俏的C功能,如int在一个条件if,等等.这是斯威夫特有原因的Bool,truefalse你不能使用Int其中的条件值Bool的预期.只是为了避免这种混乱 ......


Tim*_*eit 37

对于32位BOOL是a signed char,而在64位下它是a bool.


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
Run Code Online (Sandbox Code Playgroud)