警告只有一个位域,而不是两个?

时间:2017-05-10 11:15:33

标签: c struct compilation warnings bit-fields

受到question的启发,我有:

#include<stdio.h>
struct st
{
        int a:1;
        int b:2;
};

int main()
{
        struct st obj={1, 2};
        printf("a = %d\nb = %d\n",obj.a,obj.b);
}

我得到了:

Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c 
main.c:10:26: warning: implicit truncation from 'int' to bitfield changes value
      from 2 to -2 [-Wbitfield-constant-conversion]
        struct st obj={1, 2};
                          ^
1 warning generated.
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
a = -1
b = -2

我想我理解为什么两个位域都不能保持它们的值(按照answer),但我不明白为什么编译器只警告2,而不是{{ 1}}!有什么想法吗?

我在Mac上使用:

1

在一个旧的Linux系统中,使用gcc版本4.6.3(Ubuntu / Linaro 4.6.3-1ubuntu5),我没有收到任何相关的警告。

在Debian安装中,使用gcc版本4.9.2(Debian 4.9.2-10),我没有收到任何相关警告!

2 个答案:

答案 0 :(得分:1)

https://en.wikipedia.org/wiki/Two%27s_complement

可能会发生一些事情,也许一些实验可能有所帮助。

首先,可能是gcc足够聪明,知道单个位实际上不能为正或负,因为它只是单个位。

另一种可能性是gcc评估表达式的顺序与你的想法相反。一些编译器从右到左进行评估,在您的情况下,将错误踢出并停止。

要进行测试,请更正b的位域以保持有符号整数为“2”而不翻转符号位(3位应该有效)。如果在修复'b'时你已经为'a'生成了错误,那么你知道它只是编译器评估顺序。

如果修复'b'不会导致'a'发出警告,那么gcc会对单个位字段执行一些内部优化。

此外,将您的位域类型更改为'uint'也应该修复警告,在这种情况下,它只是表示的标志位被翻转。

快乐的编码。

修改 相关源代码:https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaChecking.cpp#L8812

答案 1 :(得分:0)

int b:2;是2位宽的有符号整数。数字2(无符号)在二进制文件中表示为10,因为source int是有符号的,所以实际上您将已签名的数字保存到内存中。

这就是你收到此警告的原因。

您可以保存为2位signed int的值为:(-2 = 11, -1 = 10, 0 = 00, 1 = 01)

两种情况下你没有得到的原因是int a:1只有1位且可以保留数字10,而没有负数。