作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
设置:
我在 C99 中定义了一个枚举:
enum MY_ENUM {TEST_ENUM_ITEM1, TEST_ENUM_ITEM2, TEST_ENUM_ITEM_MAX};
我通过编译时断言确保 TEST_ENUM_ITEM_MAX
不超过 UINT16_MAX
。我假设小端为字节顺序。
我有一个带有以下参数的序列化到缓冲区函数:
PutIntoBuffer(uint8_t* src, uint32_t count);
我将一个保存值的变量序列化到缓冲区中。对于此任务,我访问变量并保存枚举,如下所示:
enum MY_ENUM testVar = TEST_ENUM_ITEM;
PutIntoBuffer((uint8_t*) &testVar, sizeof(uint16_t));
问题:以这种方式访问枚举(它是一个 int)是否合法? C 标准能否保证预期的行为?
最佳答案
它是合法的,就像“如果 int 是 16 位它将工作”一样。只要您使用像 uint8_t
这样的字符类型,它也不违反任何指针别名规则。 (反序列化是另一个故事。)
但是,该代码不可移植。如果 int
是 32 位,则枚举常量也将变为 32 位,枚举变量本身也可能变为 32 位。然后代码将变得依赖于字节顺序,您可能最终会读到垃圾。检查 TEST_ENUM_ITEM_MAX 与 UINT16_MAX 并不能解决这个问题。
序列化枚举的正确方法是使用预先生成的只读查找表,该表保证为 8 位,如下所示:
#include <stdint.h>
enum MY_ENUM {TEST_ENUM_ITEM1, TEST_ENUM_ITEM2, TEST_ENUM_ITEM_MAX};
static const uint8_t MY_ENUM8 [] =
{
[TEST_ENUM_ITEM1] = TEST_ENUM_ITEM1,
[TEST_ENUM_ITEM2] = TEST_ENUM_ITEM2,
};
int main (void)
{
_Static_assert(sizeof(MY_ENUM8)==TEST_ENUM_ITEM_MAX, "Something went wrong");
}
如果在维护期间更新枚举,指定的初始值设定项语法可以提高数据的完整性。同样,静态断言将确保列表包含正确数量的项目。
关于c - 对 C 枚举的部分字节访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46787017/
我是一名优秀的程序员,十分优秀!