gpt4 book ai didi

c - 取消对匿名结构指针的强制转换是否违反严格的别名?

转载 作者:太空狗 更新时间:2023-10-29 15:37:29 27 4
gpt4 key购买 nike

关于 C 标准在多大程度上保证结构布局的一致性,我听说过相互矛盾的事情。有限范围的争论提到了严格的别名规则。例如,比较这两个答案:https://stackoverflow.com/a/3766251/1306666https://stackoverflow.com/a/3766967/1306666 .

在下面的代码中,我假设所有结构都是 foobarstruct { char *id; char *id 位于同一位置,如果它是唯一访问的成员,则可以安全地在它们之间进行转换。

无论转换是否会导致错误,它是否违反了严格的别名规则?

#include <string.h>

struct foo {
char *id;
int a;
};

struct bar {
char *id;
int x, y, z;
};

struct list {
struct list *next;
union {
struct foo *foop;
struct bar *barp;
void *either;
} ptr;
};

struct list *find_id(struct list *l, char *key)
{
while (l != NULL) {
/* cast to anonymous struct and dereferenced */
if (!strcmp(((struct { char *id; } *)(l->ptr.either))->id, key))
return l;
l = l->next;
}
return NULL;
}


gcc -o /dev/null -Wstrict-aliasing test.c

注意 gcc 没有错误。

最佳答案

是的,您的程序中存在多个与别名相关的问题。使用与底层对象类型不匹配的匿名结构类型的左值会导致未定义的行为。它可以用类似的东西修复:

*(char**)((char *)either + offsetof(struct { ... char *id; ... }, id))

如果您知道 id 成员在所有成员中都处于相同的偏移量(例如,它们都共享相同的前缀)。但在您的特定情况下,它是您可以做的第一个成员:

*(char**)either

因为将指向结构的指针转换为指向其第一个成员的指针(以及返回)总是有效的。

另一个问题是您对 union 的使用是错误的。最大的问题是它假定 struct foo *struct bar *void * 都具有相同的大小和表示,这不是保证。此外,访问 union 成员而不是先前存储的成员可以说是未定义的,但由于缺陷报告中的解释,可以肯定地说它等同于“重新解释转换”。但这会让您回到错误地假设相同大小/表示的问题。

您应该只删除 union ,使用 void * 成员,并将(而不是重新解释位)转换为正确的指针类型以访问指向的- 到结构(struct foo *struct bar *)或其初始 id 字段(char *)。

关于c - 取消对匿名结构指针的强制转换是否违反严格的别名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49472143/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com