我有一个可变长度的数据记录,该数据记录我使用一个结构进行建模。给定一个内存对象,我想知道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标准。
感谢您的帮助。
答案 0 :(得分:0)
关于:
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具有相同的文本),内容为:
只能通过具有以下类型之一的左值表达式访问对象的存储值:
-与对象的有效类型兼容的类型,
-与对象的有效类型兼容的类型的限定版本,
-一种类型,它是与对象的有效类型相对应的有符号或无符号类型,
-一种类型,是与对象的有效类型的限定版本相对应的有符号或无符号类型,
-集合或联合类型,其成员中包括上述类型之一(递归地包括子集合或包含的联合的成员),或
-字符类型。
buf
是5 uint8_t
的数组。可通过rec
的{{1}}访问它。与上面列出的情况进行比较:
struct record
与5 struct record
的数组不兼容。uint8_t
不是与5 struct record
数组兼容的类型的合格版本。uint8_t
不是与5 struct record
数组相对应的有符号或无符号类型。uint8_t
是聚合联合类型,但是其成员都不与5 struct record
的数组或上面列出的任何其他情况兼容。uint8_t
不是字符类型。 C标准中存在一些歧义或不完整。一个人可能会认为struct record
不是访问rec->u8
,而是仅使用struct record
来定位struct record
成员,然后访问它。通过这种解释,可以满足6.5 7,因为u8
几乎可以肯定是字符类型,因此可以满足最后一种情况。 (除非实现为扩展整数类型定义,否则它必须是字符类型。)我不会依赖于C标准的这种解释。但是,uint8_t
和u16
成员将不匹配任何大小写,因此使用它们肯定会违反C 2018 6.5 7。
根据需要解释u32
中字节的正确方法是将它们复制到结构中:
buf
标题询问“可变长度存储对象”,但是#include <string.h> // For memcpy.
…
struct record MyRecord;
memcpy(MyRecord, buf, SomeLength);
的大小为5个字节,并且没有变化。
在buf
中,如果要运行,最好将alignas(uint32_t) uint8_t buf[5];
设为alignas
。