【问题标题】:What can be assumed about the representation of true?关于真实的表示可以假设什么?
【发布时间】:2018-12-30 17:19:56
【问题描述】:

这个程序在我的机器上返回0

#include <stdbool.h>

union U {
    _Bool b;
    char c;
};

int main(void) {
    union U u;
    u.c = 3;
    _Bool b = u.b;
    if (b == true) {
        return 0;
    } else {
        return 1;
    }
}

AFAICT,_Bool是一个整数类型,至少可以存储01,而true是整数常量1。在我的机器上,_Bool 有一个sizeof(_Bool) == 1CHAR_BITS == 8,这意味着_Bool 有256 个表示。

我在 C 标准中找不到太多关于 _Bool 的陷阱表示的信息,而且我无法找到是否使用不同于 01 的表示创建 _Bool(在实现支持两个以上的表示)是可以的,如果可以,这些表示是表示真还是假。

我可以在标准中找到当 _Bool 与整数进行比较时会发生什么,如果整数具有值 0,则将其转换为 0 表示,如果它具有值则转换为 1 表示它的值不是零,因此上面的 sn-p 最终会比较两个具有不同表示的_Bools:_Bool[3] == _Bool[1]

我在 C 标准中找不到太多关于这种比较结果的信息。由于_Bool 是整数类型,我希望整数规则适用,这样相等比较仅在表示相等时才返回true,这里不是这种情况。

由于在我的平台上这个程序返回0,看来这个规则在这里不适用。

为什么这段代码会这样? (即我错过了什么?_Bool 的哪些表示是陷阱表示,哪些不是?有多少表示可以表示truefalse?填充位在其中扮演什么角色?等等)

关于_Bool 的表示,可移植的 C 程序可以假设什么?

【问题讨论】:

  • union 会导致 c 和 b 占用同一个内存区域,给 char 赋值 3 表示 b 的值也为 3,如果 NOT 为 true 则为 true,所以应该等于 -1 .
  • 我可能是错的,但你的程序对我来说像是未定义的行为
  • 为了避免整数溢出,对 _Bool 的任何非 0 (false) 赋值都存储为 1 (true)。话虽如此,您的代码似乎在这里造成了自己的混乱,因为代码显示if (true) return false,然后您质疑为什么收到false 响应。但是,我相信 @interjay 实际上有正确的答案,并且由于您的联合导致 _Bool 返回最低位,您的行为未定义。这似乎意味着联合仅用于识别一个值是奇数还是偶数。
  • 否,如果 相等,则相等比较返回 true。陈述与此目的无关
  • My answer to Is it safe to memset bool to 0? 有很多可能有用的背景信息。

标签: c boolean


【解决方案1】:

C11 标准中的脚注 122 说:

虽然 _Bool 对象中的位数至少为 CHAR_BIT,但 _Bool 的宽度(符号和值位数)可能只有 1 位。

因此,在_Bool 只有一个值位的编译器上,当您从内存中将_Bool 读取为char 时,只有一个位会生效。其他位是被忽略的填充位。

当我使用 GCC 测试您的代码时,_Bool 成员在将奇数分配给 u.c 时获得值 1,在分配偶数时获得值 0,这表明它只查看最低位。

请注意,以上仅适用于类型双关语。如果您改为将char 转换(隐式或显式转换)为_Bool,如果char 不为零,则该值将为1。

【讨论】:

  • 问题是 _Bool 在 GCC 中是否只有 1 位值。如果是这样,那么所有其他表示都是陷阱表示,并且我的示例的行为是未定义的。如果没有,那么_Bool 有许多“真”和“假”表示,而不仅仅是 2 个。
  • @gnzlbg 它在 GCC 中确实只有 1 位值(您可以通过尝试创建一个带有 _Bool b : 2 字段的位字段来检查这一点,但会失败)。但其他表示不一定是陷阱表示:未使用的位是填充位,可以有任何值。所以 0 和 1 值有很多可能的表示。编译器可以将某些填充位组合定义为陷阱表示,但看起来 GCC 并没有这样做。
  • 谢谢,有道理。
  • 仅供参考,我刚刚填写了gcc.gnu.org/bugzilla/show_bug.cgi?id=88662,因为看起来 GCC 假设 _Bool 表示是 0x0 或 0x1。
猜你喜欢
  • 2014-07-09
  • 2013-03-13
  • 1970-01-01
  • 2017-05-02
  • 2017-02-20
  • 1970-01-01
  • 2018-07-01
  • 2014-09-07
相关资源
最近更新 更多