这是严格的别名违规吗?

Is this a strict aliasing violation?

struct __packed element {
    char val;
};

void foo(struct element arr[4], uint32_t a) {
    uint32_t* i = (uint32_t*)arr;
    *i = a;
}

int main(void) {
    struct element arr[4] __aligned(4);

    foo(arr, 5);
    ...
}

与标题差不多,这是 C 中的严格别名违规吗?

假设arr的存储类型是struct element[4]

这取决于您阅读 element arr[4] 的方式,以及 arr 的分配方式。

如果您将其解读为

uint32_t value = *(uint32_t*)arr;

arr 要么是动态分配的(使用 malloc),要么是分配为具有自动存储持续时间的 int32_t 对象("on the stack"), 没关系。
如果是这种情况,您的写入会将有效类型更改为 int32_t.
但是如果你想使用与 uint32_t 无关的类型而不是字符类型来读取,这是未定义的行为。

此外,arr 需要与 int32_t 正确对齐。 (如果它是使用 malloc 获得的,它会自动获得。)


编辑完问题后发现确实是undefined behavior,因为arr分配如下:

struct element arr[4] __aligned(4);

是的,这 (*i = a) 是一个严格的别名违规。

N1570 §6.5 p7:

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

  • 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.

None满足以上要求:

  • uint32_t 与有效类型 char 不兼容。

  • 没有使用合格的 char 类型。

  • uint32_t 不是 char.

  • 的未签名版本
  • struct element 没有 uint32_t 个成员。

  • uint32_t不是字符类型。

如果原始数组的有效类型为 uint32_t 或分配给有效类型为 malloc 的分配是合法的。

uint32_t arr;
foo((struct element*)&arr, 5); // Possible pointer conversion issues still apply

void * arr = malloc(4);
foo(arr, 5);

请注意,如果转换后的地址不能存储在 uint32_t* 类型变量中,uint32_t* i = (uint32_t*)arr 也可能导致 未定义的行为 。但那是 具体实现,因此取决于您的平台。