枚举类型的按位运算

时间:2011-05-02 15:09:48

标签: c enums bit-manipulation

尝试通过以下代码将内存中的数据读入枚举时,我得到了这些奇怪的结果:

void read_memory (const unsigned, const unsigned, unsigned* const);

/* ... */

enum {DATA_0, DATA_1, DATA_2} data;
read_memory(base_addr, offset, &data);  //data = 0x0900
data >>= 8;  //data = 0x7e000000

我通过引入一个无符号类型的临时变量解决了这个问题。但我想确定理解为什么以前的方法不起作用。

首先,我知道标准不需要枚举类型的特定宽度,只要可以表示所有成员。事实上,6.7.2.2指出:

  

每个枚举类型应与char,有符号整数类型或者   无符号整数类型。

但是,由于从内存中读取的原始数据适合于char,我认为它不应该是一个问题。 此外,如果我理解正确,“兼容”意味着您可以像使用这种类型一样使用它。特别是,枚举类型的对象可以是按位移位运算符的操作数。 我也知道签名可能是一个问题,因为我们不知道枚举是否签名。但是,据我所知,0x0900似乎没有签名。

问题出在哪里?

3 个答案:

答案 0 :(得分:2)

您(在我看来,命名错误的)read_memory()函数读取了多少数据?如果这与sizeof data的值不同,则表示您遇到问题。仅仅因为枚举值足够小char并不意味着编译器选择单个char;也许操作int大小的数字的指令更快,和/或存在对齐问题。

答案 1 :(得分:0)

在调试器外部测试代码之后,结果表明它的行为正确并且gdb显示的信息不准确。

事实上,分析反汇编的机器代码显示它与C源代码行不匹配。结果,该函数的结尾被认为(通过gdb)成为data >>= 8;指令的一部分。 这个问题对我来说仍然很奇怪,因为我用-g -O0编译和链接了所有源文件和目标文件。

也许是编译器中的一个错误......

编辑:实际上它与gdb无关,编译器发出的调试符号是错误的。

答案 2 :(得分:0)

枚举类型已签名,因此当您移位时,符号位(1)将被复制到数字位上。