gpt4 book ai didi

c++ - MSVC 1 位枚举类型等于 -1 且相等性测试失败

转载 作者:太空宇宙 更新时间:2023-11-04 06:47:12 26 4
gpt4 key购买 nike

我已经定义了一个枚举类型的位域来匹配嵌入式系统中的一组位。我正在尝试在 MSVC 中编写测试工具对于代码,但是比较应该相等的值会失败。

定义如下:

typedef enum { SERIAL, PARALLEL } MODE_e;
typedef union {
struct {
TYPE_e Type : 1; // 1
POSITION_e 1Pos : 1; // 2
POSITION_e 2Pos : 1; // 3
bool Enable : 1; // 4
NET_e Net : 1; // 5
TYPE_e Type : 1; // 6
bool En : 1; // 7
TIME_e Time : 3; // 8-10
MODE_e Mode : 1; // 11
bool TestEn : 1; // 12
bool DelayEn : 1; // 13
MODE_e Mode : 1; // 14
bool xEn : 1; // 15
MODE_e yMode : 1; // 16
bool zEnable : 1; // 17
} Bits;
uint32_t Word;
} BITS_t;

稍后以下比较失败:

Store.Bits.Mode = PARALLEL;
if (store.Bits.Mode == PARALLEL)
...

我检查了调试器中的 Mode bool 值,它看起来很奇怪。 Mode 的值为-1。

就好像 MSVC 认为这个值是一个 two's complement数字,但 1 位宽,所以 0b1 是十进制 -1。枚举将 PARALLEL 设置为 1,因此两者不匹配。

使用 LLVM 在嵌入式方面进行比较效果很好或海湾合作委员会。

哪种行为是正确的?我假设 GCC和 LLVM 在位字段等领域比 MSVC 对 C 标准的支持更好。更重要的是,我能否在不对嵌入式代码进行重大更改的情况下解决这一差异?

最佳答案

详细剖析这个,你有以下问题:

  • 不能保证 Type : 1 是 MSB 或 LSB。通常,根本无法保证内存中的位域布局。

  • 如其他答案中所述,枚举变量(与枚举常量不同)具有实现定义的大小。这意味着您无法便携地知道它们的大小。此外,如果大小与 int_Bool 不同,则编译器根本不需要支持它。

  • 枚举通常是有符号整数类型。当你创建一个带符号类型的大小为 1 的位域时,包括标准在内的任何人都不知道这意味着什么。它是您打算存储在那里的符号位还是数据?

  • 未指定 C 标准称为位域内“存储单元”的大小。通常它是基于对齐的。 C 标准确实保证,如果您有多个相同类型的位字段彼此尾随,则它们必须合并到同一个存储单元中(如果有空间)。对于不同的类型,没有这样的保证。

    当您从一种类型如 POSITION_e 转换为另一种类型 bool 时,编译器将它们放在不同的存储单元中是很常见的。实际上,这意味着每当发生这种情况时,填充位插入的风险就很高。许多主流编译器实际上就是这样做的。

  • 此外,结构或 union 可以在任何地方包含填充字节。

  • 此外还有字节顺序问题。

结论:位域不能用于需要任何形式的可移植性的程序中。它们不能用于内存映射。

此外,您真的不需要所有这些抽象层 - 它只是一个简单的拨码开关,而不是航天飞机! :)


解决方法:

我强烈建议放弃所有这些,转而使用普通的 uint32_t。您可以使用纯整数常量屏蔽单个位:

#define DIP_TYPE (1u << 31)
#define DIP_POS (1u << 30)
...

uint32_t dipswitch = ...;
bool actuator_active = dipswitch & DIP_TYPE; // read
dipswitch |= DIP_POS; // write

这是一种高度便携、定义明确、标准化且符合 MISRA-C 标准的软件 - 您甚至可以在不同的字节顺序架构之间移植它。它解决了上述所有问题。

关于c++ - MSVC 1 位枚举类型等于 -1 且相等性测试失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56344190/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com