【问题标题】:Why is a BOOL a signed char?为什么 BOOL 是有符号字符?
【发布时间】:2010-09-30 23:42:26
【问题描述】:

前几天,一位用户向我报告了一个关于工具栏项在应该启用时被禁用的错误。验证代码(为您的利益而简化)如下所示:

- (BOOL) validateToolbarItem: (NSToolbarItem *) toolbarItem {

    NSArray* someArray = /* arrray from somewhere*/

    return [someArray count];
}

我花了几分钟才意识到 -count 返回一个 32 位无符号整数,而 BOOL 是一个 8 位有符号字符。碰巧在这种情况下 someArray 中有 768 个元素,这意味着低 8 位都是 0。当 int 在返回时被强制转换为 BOOL 时,它解析为 NO,即使人类会期望答案是YES

我已经将我的代码更改为return [someArray count] > 0; 但是,现在我很好奇为什么 BOOL 真的是一个有符号字符。在某种程度上,这真的比 int 更好吗?

【问题讨论】:

  • 您会经常看到 !![someArray count] 正是因为这个原因(与 > 0 的作用几乎相同)
  • 如果您再仔细考虑一下您的问题,您会发现它几乎等同于“为什么 any type 与 int 不同?”因为答案几乎相同。存在较小的标量类型,因为它们不需要完整的 int 范围。 BOOL 甚至不需要有符号字符的全部范围,但没有可用的更小的类型。
  • 你真的不应该将除了布尔表达式的结果之外的任何东西分配给布尔变量,无论使用什么实际类型来实现布尔变量。去检查你的代码是否有其他类似的可憎行为。

标签: objective-c


【解决方案1】:

(到目前为止)给出的答案集中在为什么 BOOL 不是 int 上。答案很明确:char 比 int 小,而在 80 年代设计 Objective-C 时,减少几个字节总是好的。

但您的问题似乎也在问,“为什么 BOOL 是有符号的而不是无符号的?”为此,我们可以在/usr/include/objc/objc.h 中查看 BOOL 的类型定义:

typedef signed char     BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used.

所以有一个答案:Objective-C 设计者不想将 BOOL 类型定义为 char,因为在某些系统上,在某些编译器下(请记住,Objective-C 早于 ANSI C,因此 C 编译器有所不同),char已签名,在某些情况下,未签名。设计者希望 @encode(BOOL) 在平台之间返回一致的值,因此他们将签名包含在 typedef 中。

但这仍然引出了一个问题:为什么要签名而不是未签名?我对此没有明确的答案。我想原因是他们必须选择一个或另一个,并决定签署。如果我必须进一步推测,我会说这是因为 int 默认情况下是有符号的(也就是说,如果它们不包含签名限定符)。

【讨论】:

  • 如果场景中没有逻辑,那么这不是一个合乎逻辑的决定。没有答案?这在形式科学中很糟糕。随机性不应该应用于设计决策。尤其是在设计形式语言时。道德?不知道。但是,那么怀疑 O-C 是否是一种有价值的语言似乎是合理的。
  • @cedbeu:是什么让你说有 no 逻辑?关于为什么BOOL 是某种类型的char,有很多逻辑。唯一不清楚的是为什么它是签名的而不是未签名的,在这种情况下,两者都是相当随意的(意味着你必须选择一个,但选择哪一个并不是什么大问题)。
  • 是的。只是,我不喜欢这个主意。我倾向于认为,如果您必须做出——即使是很小的——任意决定,这意味着核心设计存在一些缺陷。但你是对的,这可能没什么大不了的,而且可能在每种语言的某个时候都有这样任意的设计决策 (brrr)。
【解决方案2】:

回到更简单的时代。

BOOL 类型是在 CPU 自然地使用 8 位类型时创建的,很少填充到 16 位或 32 位。然而,内存是稀缺的,将 1 位塞进 4 个字节实际上会消耗大量额外的内存。

请注意,BOOL 可能比 C++ 的 _bool 早了很长一段时间(iirc--他们可能差不多。当 NeXT 选择 Objective-C 时,C++ 也很受欢迎。

【讨论】:

    【解决方案3】:

    一个明显的答案是它小四倍(在典型的 32 位和 64 位架构上),并且没有任何对齐要求。

    【讨论】:

    • 具有讽刺意味的是,在大多数编译器/体系结构上,它会填充其他 3 个字节,以便可以更快地写入 32 位读/写
    • @Paul:我从未在结构中看到任何编译器垫char - 你能举个例子吗?由于连续的存储要求,它肯定不会在数组中执行此操作。
    • 结构 x { int a;字符 b;诠释 c; }; sizeof(x) == 12。他说的大概就是这个。
    • @sharth:这种情况下的填充是对齐c,具体与b的类型没有太大关系。
    • 我看看能不能通过 kd 找到一个例子,不过我可能已经写满了。你绝对是正确的 wrt 数组。
    【解决方案4】:

    布尔值需要只需要一个位(0 或 1),但是标准系统将字节视为最小单位。以 8 位字节表示的 bool 比 32 位整数小 4 倍,这就是字节优于整数的动机。

    【讨论】:

      【解决方案5】:

      Bools 在节省一点空间和将值限制为 0 或 1 方面很有用。它是一种较小的类型,原因与您可能使用 float 而非 double 或 short 而非 long 的原因相同。只是空间问题。

      这就是为什么最好明确您的转换,并且在布尔值的情况下,在相同类型的两个之间执行实际的逻辑比较以得到实际的布尔值而不是截断值。

      p>

      【讨论】:

        【解决方案6】:

        它更小,仅此而已。

        【讨论】:

          猜你喜欢
          • 2020-06-02
          • 2010-09-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-20
          • 2014-09-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多