gpt4 book ai didi

c - 通过结构体访问可变长度内存对象是否定义良好?

转载 作者:行者123 更新时间:2023-11-30 16:15:33 24 4
gpt4 key购买 nike

我有一个使用结构建模的可变长度数据记录。给定一个内存对象,我想知道 C 标准中是否明确定义了以下内容。

我使用以下结构对问题进行建模:

struct record
{
uint32_t type;
union
{
uint8_t u8;
uint16_t u16;
uint34_t u32;
};
};

对于相关平台,

sizeof(struct record) == 8

下面的选角是否能够明确定义?

alignas(uint32_t) uint8_t buf[5];
struct record *rec = (struct record*)buffer;

通过指针访问内存对象怎么样?也就是说,访问

uint8_t x = rec->u8;
rec->u8 = x+1;

明确定义了吗?我完全预计 u16 和 u32 访问没有明确定义,可能会导致异常。

如果您能引用 c11 标准,我们将不胜感激。

感谢您的帮助。

最佳答案

别名违规

关于:

alignas(uint32_t) uint8_t buf[5];
struct record *rec = (struct record*)buf;
uint8_t x = rec->u8;

(请注意,原文中的 buffer 显然是一个错误,此处已更正为 buf。)

这违反了 C 2018 6.5 7(C 2011 有相同的文本),其中规定:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:

— a type compatible with the effective type of the object,

— a qualified version of a type compatible with the effective type of the object,

— a type that is the signed or unsigned type corresponding to the effective type of the object,

— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,

— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or

— a character type.

buf 是一个由 5 个 uint8_t 组成的数组。它是通过rec 访问的,它是一个struct record。将此与上面列出的案例进行比较:

  • struct record 与 5 个 uint8_t 数组不兼容。
  • struct record 不是与 5 uint8_t 数组兼容的类型的限定版本。
  • struct record 不是对应于 5 个 uint8_t 数组的有符号或无符号类型。
  • struct record 是聚合 union 类型,但其成员均不与 5 个 uint8_t 数组或上面列出的任何其他情况兼容。
  • struct record 不是字符类型。

C 标准中存在一些含糊之处或不完整。人们可能会将 rec->u8 解释为不访问 struct record,而只是使用 struct record 来定位 u8 > 成员,然后访问它。通过这种解释,可以满足 6.5 7,因为 uint8_t 几乎肯定是字符类型,因此满足最后一种情况。 (它必须是字符类型,除非实现为其定义了扩展整数类型。)我不会依赖 C 标准的这种解释。但是,u16u32 成员不会匹配任何大小写,因此使用它们肯定会违反 C 2018 6.5 7。

解决方案

根据需要解释 buf 中的字节的正确方法是将它们复制到结构中:

#include <string.h> // For memcpy.

struct record MyRecord;
memcpy(MyRecord, buf, SomeLength);

其他问题

标题询问“可变长度内存对象”,但是buf的大小是5个字节并且不会变化。

alignas(uint32_t) uint8_t buf[5]; 中,如果它能正常工作,alignas 最好是 alignas(struct record) .

关于c - 通过结构体访问可变长度内存对象是否定义良好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57045349/

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