比特域与一个(负)整数,未定义的行为或编译器错误的比较?

Lyk*_*yke 15 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;
}
Run Code Online (Sandbox Code Playgroud)

这是从重新发布的CSmith测试中获得的,这里将更详细地讨论这种情况.

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

Ano*_*mie 12

有趣的问题.

根据C99标准草案6.5.17.1,类型(0, s.f1)是相同的s.f1,其(每6.7.2.1.9)是"由...组成1个比特的无符号整数型".这是一种算术类型,因为它是一个整数类型,它的精度是1(每6.2.6.2.6,6.6.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,因此它被提升为(signed)int(根据6.3.1.1.2).然后由于两个操作数都是(带符号)整数,因此公共实数类型是有符号整数(根据6.3.1.8),因此比较结果应为0.


Oli*_*rth 5

AFAIK,类型s.f1unsigned int.我相信逗号操作符是一个红鲱鱼; 这种比较相当于int y = x >= s.f1;.应用"通常的算术转换"(C99 6.3.1.8),在进行比较时x转换为unsigned int; 这种转换是明确定义的(它将导致UINT_MAX-2.因此它会更大.所以答案应该是1.