[英]What happens when I cast uint8_t array to uint32_t?
假设我有这个数组:
uint8_t arr[10];
位于地址0x00
。
然后我想将其中的一部分分配给uint32_t值。 arr [1],arr [2],arr [3]和arr [4]的聚合为32位整数。 这是一个例子:
uint8_t arr[10];
uint32_t i;
i = *( (uint32_t *)&arr[1] );
困扰我的是arr[1]
位于地址不是四的倍数(地址0x01)。 所以问题是:32位平台会发生什么? 这是合法的吗,与标准的uint32
任务相比,它有一些缺点吗?
这是非法的,因为它违反了严格的别名规则,导致未定义的行为 。
请改用memcpy
:
memcpy(&i, &arr[1], sizeof(i));
但请注意,此代码假定主机字节序。 如果您需要与字节顺序无关的代码,请使用位移和屏蔽将4个值组合成整数,或者在memcpy
之后交换字节(编译器通常会为此提供某种内在函数)。
类型惩罚违反了有效类型规则,即C标准的第6.5节第6和第7节。 这些表示您无权访问具有与声明的类型不同的对象。 (这些规则有一些复杂的例外,但这里不适用。)
这样做会使您的程序处于未定义状态,并且可能会发生错误。 根据经验,除非你确切知道自己在做什么,否则永远不要做指针演员。
如果你真的需要在字节表示和另一种类型之间切换,最简单的方法是使用union
union twist {
unsigned char c[sizeof(uint32_t)];
uint32_t u;
} val = { .c = { [0] = 7, } };
// now use
val.u
由于别名规则导致的这种未定义的行为,您只需使用一个赋值:
i = arr[1];
它将uint8_t
值转换为uint32_t
值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.