Vil*_*ray 20 c c99 strict-aliasing void-pointers type-punning
我最近遇到了严格的别名规则,但是我无法理解如何在void *不违反规则的情况下执行类型惩罚.
我知道这违反了规则:
int x = 0xDEADBEEF;
short *y = (short *)&x;
*y = 42;
int z = x;
Run Code Online (Sandbox Code Playgroud)
而且我知道我可以安全地使用C99中的联合进行类型惩罚:
union{
int x;
short y;
} data;
data.x = 0xDEADBEEF;
data.y = 42;
int z = data.x;
Run Code Online (Sandbox Code Playgroud)
但是如何void *在C99中安全地执行打字?以下是正确的:
int x = 0xDEADBEEF;
void * helper = (void *)&x;
short *y = (short *)helper;
*y = 42;
int z = x;
Run Code Online (Sandbox Code Playgroud)
我怀疑代码仍然会破坏严格的别名规则,因为变量x地址的内存可以由两者修改x并且可以解除引用y.
如果未定义类型 - 惩罚void *,那么void *C99中的目的是什么?
R..*_*R.. 21
void *与打字无关.其主要目的是:
允许通用分配和释放操作,这些操作不关心调用者在那里存储的对象的类型(例如malloc和free).
允许调用者通过函数将指针传递给任意类型,该函数将通过回调将其传回(例如qsort和pthread_create).在这种情况下,编译器不能强制执行类型检查; 这是你的责任,写调用者和回调,以确保回调访问正确类型的对象时.
指针void也用于memcpy实际操作对象的一些地方(例如)作为对象的重叠unsigned char []表示.这可以被视为类型惩罚,但它不是别名违规,因为char类型被允许别名来访问其表示.在这种情况下,unsigned char *也可以工作,但void *具有指针自动转换为的优势void *.
在您的示例中,由于原始类型是int并且不是联合,因此没有合法的方式来键入pun并将其作为short.您可以将值复制x到联合,在那里执行定义良好的类型惩罚,然后将其复制回来.一个好的编译器应该完全省略副本.或者,您可以将写入分解为char写入,然后它将是合法的别名.