受此启发,我有:

#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

我想我理解为什么两个位字段都不能保存它们的值(根据这个question),但是我不理解为什么编译器只警告2,而不是1!有什么想法吗?
我在Mac中使用:
Georgioss-MacBook-Pro:~ gsamaras$ gcc -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.38)
Target: x86_64-apple-darwin16.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

在一个旧的Linux系统中,GCC4.6.3版(Ubuntu/Linaro 4.6.3-1ubuntu5),我没有收到相关的警告。
在Debian安装中,GCC4.9.2版(Debian4.9.2-10)没有相关警告!

最佳答案

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

关于c - 警告只有一个位域,而不是两个位域?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43890884/

10-11 15:16