[Objective-C ++]为什么在64位而不是在32位中允许将对象分配给BOOL类型变量

问题描述 投票:1回答:4

ViewController.mm中的以下代码将在64位环境中成功编译(没有任何警告或错误)。

- (void)viewDidLoad {
    [super viewDidLoad];
    BOOL var = [[NSUserDefaults standardUserDefaults] objectForKey:@"foo"];
    NSLog(@"%d", var);
}

但是当我将运行目标更改为32位设备(例如,iPhone 5)时,它会显示如下错误:

 Cannot initialize a variable of type 'BOOL' (aka 'signed char') with an rvalue of type 'id _Nullable'

我知道这个任务是错误的,但为什么它在第一种情况下允许?

objective-c c++11 32bit-64bit objective-c++
4个回答
3
投票

对于64位iOS,BOOL类型使用C99 _Bool类型(有时也可用作bool)。该类型被定义为仅具有两个值0或1.将任何其他值分配给该类型的变量使得它取值1.(即,所有非零值变为1。)

因此,赋值不会截断按位值,可能会将非零值转换为零。因此,它在某个方面是“安全的”,并且没有理由发出警告。 (对于一个天真的开发人员来说,如果没有理解对象指针与其值之间的差异,可能仍然会感到惊讶,正如其他答案所解决的那样,但这是另一回事。)


1
投票

错误表示您正在将对象分配给BOOL类型的变量。要解决它,您需要使用objectForKey:将从BOOL返回的对象转换为boolValue变量。

BOOL var = [[[NSUserDefaults standardUserDefaults] objectForKey:@"foo"] boolValue];

1
投票

你的代码: BOOL var = [[NSUserDefaults standardUserDefaults] objectForKey:@"foo"]; 将对象的地址分配给某个大小的int ...

这几乎总是不是你想要的。你可能想要: BOOL var = [[[NSUserDefaults standardUserDefaults] objectForKey:@"foo"]boolValue];

如果您确实希望根据该对象的存在进行分配,您可以执行以下操作: BOOL var = !![[NSUserDefaults standardUserDefaults] objectForKey:@"foo"];

原因是,如果地址的底部8位全部为0,则它​​可能是有效对象,但是将是假值,这将是截断赋值的结果。

int main(int argc, const char * argv[]) {

    BOOL b = 2;
    if (b == YES)
    {
        NSLog(@"I guess you are right");
    }else{
        NSLog(@"nope");
    }

打印:nope


1
投票

有几个方面可以解释为什么这个有效,其中很多都是历史性的东西,因为它曾经是那样。

  1. bool是一种相对较新的类型。如果你看一下较旧的C代码,你会经常看到他们只是使用int,或者像Objective-C编译器一样,并声明他们自己的BoolBOOLBoolean类型。
  2. 回到最初定义Objective-C时,他们使用最小的类型(signed char)作为他们的BOOL类型。
  3. C if语句总是允许使用指针作为其条件,以测试指针不是NULL(或ObjC的情况下的nil)。
  4. bool被添加到C标准时,它基本上被定义为“if所采用的类型”,因此必须具有所有相同的行为,包括允许您提供指向bool的指针,并将其评估为false如果niltrue否则。
  5. Apple无法在旧机器上将BOOL更改为bool,因为它会改变@encode()BOOL返回的符号,并使旧程序无法链接到与新库相同的过程(反之亦然)。
  6. 当64位iOS到来时,许多数据类型已经改变了大小,因此Apple可以安全地将BOOL更改为bool,因为没有旧程序需要能够在与新库相同的内存空间中运行。一切都是新的。

因此,在BOOL的新定义为bool的平台上,您遇到了C的向后兼容性功能,让您检查NULL指针。在较旧的平台上,BOOL被定义为signed char,显然不适合指针,并且没有指针的特殊酱,因此导致警告。

© www.soinside.com 2019 - 2024. All rights reserved.