【发布时间】:2010-05-14 19:23:16
【问题描述】:
今天我在尝试位域时发现了令人震惊的行为。为了讨论和简单起见,这里有一个示例程序:
#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
这是使用“g++ -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,而实际上数字溢出并且为零。
幸运的是,据我所知,我关心的代码没有溢出,但这种情况让我感到害怕——这是一个已知的错误、一个功能,还是这是预期的行为?我什么时候可以期望 gcc 在这方面是正确的?
编辑(回复:已签名/未签名):
它被视为无符号,因为它被声明为无符号。将其声明为 int 你会得到输出(使用 O0):
3 位字段转换为 int:-1
3 位字段转换为 int:0
在这种情况下,使用 -O2 会发生更有趣的事情:
3 位字段转换为 int:7
3 位字段转换为 int:8
我承认 attribute 使用起来很可疑;在这种情况下,我担心的是优化设置的差异。
【问题讨论】:
-
chedcked gcc 4.4.1 - 输出为 7/0 有/无优化
-
我承认我使用的是 4.1.2 - 感谢您的提醒。
-
如果你把
__attribute__((__packed__))放在整个结构之后会发生什么?
标签: c++ c gcc bit-fields optimization