我最近遇到了严格的别名规则,但我很难理解如何在不违反规则的情况下使用 void *
执行类型双关。
我知道这违反了规则:
int x = 0xDEADBEEF;
short *y = (short *)&x;
*y = 42;
int z = x;
而且我知道我可以安全地使用 C99 中的 union 来进行类型双关:
union{
int x;
short y;
} data;
data.x = 0xDEADBEEF;
data.y = 42;
int z = data.x;
但是如何使用 void *
在 C99 中安全地执行类型双关?以下是否正确:
int x = 0xDEADBEEF;
void * helper = (void *)&x;
short *y = (short *)helper;
*y = 42;
int z = x;
我怀疑代码仍然会违反严格的别名规则,因为变量 x
地址处的内存可以被 x
和取消引用的 y 修改
。
如果通过 void *
未定义类型双关,那么 C99 中 void *
的目的是什么?
最佳答案
void *
与类型双关无关。其主要目的是:
允许不关心调用者存储在那里的对象类型的通用分配和释放操作(例如
malloc
和free
) .允许调用者通过函数传递指向任意类型的指针,该函数将通过回调将其传回(例如
qsort
和pthread_create
) .在这种情况下,编译器无法强制执行类型检查;在编写调用程序和回调时,您有责任确保回调访问具有正确类型的对象。
指向 void
的指针也用在一些地方(如 memcpy
),它们实际上作为覆盖 unsigned char []
对对象进行操作> 对象的表示。这可以被视为类型双关,但它不是别名违规,因为 char
类型允许对任何内容进行别名以访问其表示。在这种情况下,unsigned char *
也可以,但是 void *
的优点是指针会自动转换为 void *
。
在您的示例中,由于原始类型是 int
而不是 union ,因此没有合法的方式来类型双关并将其作为 short
访问。您可以改为将 x
的值复制到 union ,在那里执行明确定义的类型双关,然后将其复制回来。一个好的编译器应该完全省略副本。或者,您可以将写入分解为 char
写入,然后这将是合法的别名。
关于c - 在不违反 C99 中严格的别名规则的情况下使用 void * 输入双关语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15745030/