这是严格的别名违规吗?
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
也可能导致 未定义的行为 。但那是 具体实现,因此取决于您的平台。
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
也可能导致 未定义的行为 。但那是 具体实现,因此取决于您的平台。