位域与(负)整数、未定义行为或编译器错误的比较?

标签 c

这是一个小程序。这应该打印 0 或 1,还是它有未定义的行为?

#include <stdio.h>
struct S0 {
  unsigned f1 : 1;
};

struct S0 s;

int main (void) {
  int x = -3;
  int y = x >= (0, s.f1);
  printf ("%d\n", y);
  return 0;
}

这取自重新发送的 CSmith测试,此案例讨论更多here .

特别是,GCC、KCC 和 CompCert 输出 0,而 MSVC 2010、ICC 12.0.2 和最近的 Clang 输出 1。

最佳答案

有趣的问题。

根据C99草案标准6.5.17.1,(0, s.f1)的类型与s.f1的类型相同,即(per 6.7.2.1.9) 是“由 1 位组成的无符号整数类型”。由于是整数类型,这是一种算术类型,其精度为 1(根据 6.2.6.2.6 和 6.2.6.1.3 暗示没有填充位),因此其秩小于 int (根据 6.3.1.1.1 下的第二项;int 的精度至少为 15,因为它必须能够表示 -32767 到 32767 范围内的值(参见 5.2.4.2.1))。

由于 x 和表达式 (0, s.f1) 都具有算术类型,因此执行通常的算术转换(根据 6.5.8.3)。由于 int 可以表示 s.f1 的整个值范围,因此它被提升为(有符号)int(根据 6.3.1.1.2)。然后因为两个操作数都是(有符号的)整数,所以常见的实数类型是有符号的 int(根据 6.3.1.8),因此比较的结果应该是 0。

关于位域与(负)整数、未定义行为或编译器错误的比较?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6695193/

相关文章:

c - C 中的简单 toupper 编码

无法将函数的指针值返回到 main

javascript - 浏览器中的mp3流解码

c - 为什么 !0 等于 1 而不是 -1?

c - 在 Linux 中向鼠标驱动程序提供备用数据

c - 将链表的头与其中的链接交换?

c++ - 如何在 C++ 中的 2 个函数集之间切换?

c - 第二个 "ch = getchar(); "有什么意义

c - 下面的 C 代码的输出是否因平台而异?

c - 在 for 循环中使用结构的问题