今天我与位域实验时发现了令人震惊的行为。为了讨论和简单起见,下面是一个示例程序:GCC,-02,和位域 - 这是一个错误或功能?
#include <stdio.h>
struct Node
{
int a:16 __attribute__ ((packed));
int b:16 __attribute__ ((packed));
unsigned int c:27 __attribute__ ((packed));
unsigned int d:3 __attribute__ ((packed));
unsigned int e:2 __attribute__ ((packed));
};
int main (int argc, char *argv[])
{
Node n;
n.a = 12345;
n.b = -23456;
n.c = 0x7ffffff;
n.d = 0x7;
n.e = 0x3;
printf("3-bit field cast to int: %d\n",(int)n.d);
n.d++;
printf("3-bit field cast to int: %d\n",(int)n.d);
}
该程序故意导致3位位域溢出。这里的(正确的)输出使用的 “g ++ -O0” 编译时:
3位字段浇铸到int:7
3位字段浇铸到int:0
这里的使用 “克++ -O2”(-O3和)时编译的输出:
3位字段浇铸到int:7
3位字段铸为int:8
检查后者实施例的组件中,我发现这一点:
movl $7, %esi
movl $.LC1, %edi
xorl %eax, %eax
call printf
movl $8, %esi
movl $.LC1, %edi
xorl %eax, %eax
call printf
xorl %eax, %eax
addq $8, %rsp
的优化刚才插入的 “8”,假定7 + 1 = 8时实际上溢出次数并且是零。
幸好我在乎据我所知不会溢出,但这种情况让我害怕的代码 - 这是一个已知的bug,功能,或者这是预期的行为?我什么时候可以期待gcc对此有所了解?
编辑(RE:符号/无符号):
,因为它被声明为unsigned它被视为无符号。声明为INT你得到的输出(带O0):
3位字段强制转换为int:-1
3位字段强制转换为int:0
一个更有趣的事情与-O2发生在这种情况下:
3位字段浇铸到int:7
3位字段浇铸到int:8
我承认属性是一个可腥的东西使用;在这种情况下,这是我关心的优化设置的差异。
chedcked gcc 4.4.1 - 输出是7/0有/无优化 – dimba 2010-05-14 19:33:30
我承认我使用4.1.2 - 谢谢你的提升。 – Rooke 2010-05-14 19:39:41
如果在整个结构之后放置__attribute __((__ packed __)),会发生什么? – 2010-05-14 19:48:52