当我将uint8_t数组转换为uint32_t时会发生什么?

时间:2016-08-17 07:44:34

标签: c arrays

假设我有这个数组:

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作业相比,它有哪些缺点?

3 个答案:

答案 0 :(得分:5)

这是非法的,因为它违反了严格的别名规则,导致undefined behaviour

改为使用memcpy

memcpy(&i, &arr[1], sizeof(i));

但请注意,此代码假定主机字节序。如果您需要与字节顺序无关的代码,请使用位移和屏蔽将4个值组合为整数,或在memcpy之后交换字节(编译器通常会为此提供某种内在函数)。

答案 1 :(得分:3)

类型惩罚违反了有效类型规则,即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

答案 2 :(得分:0)

由于别名规则导致的这种未定义行为,您只需使用赋值:

i = arr[1];

uint8_t值转换为uint32_t值。