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]
答案 0 :(得分:5)
是的,此(*i = a
)是严格的别名违规。
N1570§6.5p7:
对象的存储值只能由具有其中一个的左值表达式访问 以下类型:88)
- 与对象的有效类型兼容的类型
- 与对象的有效类型兼容的类型的限定版本,
- 对应于有效类型的有符号或无符号类型的类型 对象,
- 对应于合格版本的有符号或无符号类型的类型 有效的对象类型,
- 聚合或联合类型,其中包含上述类型之一 成员(包括,递归地,子集合或包含的联合的成员),或
- 字符类型。
以上要求均未达到:
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* i = (uint32_t*)arr
类型变量中,uint32_t*
也可能会导致未定义的行为。但这是特定于实现的,因此取决于您的平台。
答案 1 :(得分:3)
这取决于您阅读arr
的方式以及uint32_t value = *(uint32_t*)arr;
的分配方式。
如果您将其视为
arr
和malloc
要么动态分配(使用int32_t
),要么分配为具有自动存储持续时间的int32_t
对象(“在堆栈上”),
没关系。
如果是这种情况,您的写入会将有效类型更改为uint32_t
但是,如果您想使用与arr
无关的类型而不是字符类型进行读取,则它是未定义的行为。
此外,int32_t
需要与malloc
正确对齐。 (如果是使用arr
获得的,则会自动生成。)
在编辑问题之后,很明显它确实是未定义的行为,因为struct element arr[4] __aligned(4);
分配如下:
ng-model