为什么这段代码会产生所示的输出?
#include<stdio.h>
struct sample{
int x:1;
}a[5]={0,1,2,3,4};
int main(){
int i;
for(i=0;i<5;++i){
printf("%d ",a[i].x);
}
return 0;
}
使用 OnlineGDB 编译和执行时的输出是:
0 -1 0 -1 0
最佳答案
int x:1
充当有符号的一位整数。根据 C 2018 6.7.2 5,实现可能会将声明为 int
的位字段视为 unsigned int
,但您使用的 C 实现似乎将其视为已签名。
此外,C 实现使用二进制补码。在二进制补码中,一个 n 位整数有 1 个符号位和 n−1 个值位。由于您的整数是一位,因此它有一个符号位和零值位。根据二进制补码规范 (C 2018 6.2.6.2 2),符号位的值为 −2M,其中 M 是值位数。因为它是零,所以符号位的值为 −20 = −1。
因此,当位为零时,位域的值为 0,当位为 1 时,位域的值为 -1。1
在使用 ={0,1,2,3,4};
进行初始化期间,数组中的第一个位字段设置为零。但是,其他溢出位域中可表示的值。根据 C 2018 6.3.1.3 3,生成实现定义的结果或引发实现定义的信号。此 C 实现似乎正在生成源值的低位作为位域中位的值。这会在五个位字段中产生位 0、1、0、1 和 0,分别表示值 0、-1、0、-1 和 0。因此,当它们被打印时,值 0、-1、 0、-1 和 0 结果。
脚注
1 这可能被视为二进制补码正常工作方式的自然结果:对于八位,范围是 −128…127。对于四位,范围是 −16…15。比特越来越少,范围是-8…7、-4…3、-2…1,最后是-1…0。
关于c - 为什么一位 `int` 位域的值是 0 和 −1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60489275/