【问题标题】:Bitwise operations on enum types枚举类型的按位运算
【发布时间】:2011-05-02 15:09:48
【问题描述】:

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

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、有符号整数类型或 无符号整数类型。

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

那么问题出在哪里?

【问题讨论】:

  • 什么编译器和什么目标?在执行的各个阶段,您如何确定data 的值?也许显示read_memory()的代码。
  • 你如何输出你的“数据”来得到那个结果?预期的结果是什么?您还可以使用调试器作为 gdb 来跟踪变量的实际值
  • data 的值是通过 gdb 确定的。目标是我们正在使用特定编译器(带有 gcc 前端)开发的多核嵌入式系统。调用read_memorydata 的值很好,但在转换后它应该是0x0009 而不是0x7e000000。我补充说,我也尝试左移 8 位和右移 4 位,并得到相同的结果。

标签: c enums bit-manipulation


【解决方案1】:

你的read_memory() 函数读取了多少数据?如果这与sizeof data 的值不同,那么您就有问题了。仅仅因为枚举值对于char 来说足够小,并不意味着编译器必须 选择单个char。也许操作 int 大小的数字的指令更快,和/或存在对齐问题。

【讨论】:

  • 基本上,read_memory() 这样做:*data_ = *(volatile unsigned int*)(base_addr + offset); 我还检查了sizeof data == sizeof(unsigned)。有什么想法吗?
【解决方案2】:

在调试器之外测试了代码,结果发现它的行为是正确的,是gdb显示的信息不准确。

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

可能是编译器中的错误...

编辑:其实和gdb没有关系,是编译器发出的调试符号出错了。

【讨论】:

    【解决方案3】:

    枚举类型是有符号的,因此当您移动符号位 (1) 时,会复制数字位。

    【讨论】:

    • C 标准说:类型的选择是实现定义的,但应该能够表示枚举所有成员的值。 并且脚注:实现可能会延迟选择哪种整数类型,直到看到所有枚举常量。因此,枚举类型也可能是无符号的。
    猜你喜欢
    • 2022-03-30
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多