键入与void *的双关语不打破严格走样规则在C99 [英] Type punning with void * without breaking the strict aliasing rule in C99

查看:131
本文介绍了键入与void *的双关语不打破严格走样规则在C99的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我遇到了严格别名规则,但我无法理解如何使用无效* 来没有打破规则执行类型双关语。

I recently came across the strict aliasing rule, but I'm having trouble understanding how to use void * to perform type punning without breaking the rule.

我知道这违反规则:

int x = 0xDEADBEEF;

short *y = (short *)&x;
*y = 42;

int z = x;

和我知道,我可以放心地使用工会为C99型双关:

And I know that I can safely use a union in C99 for type-punning:

union{
    int x;
    short y;
} data;

data.x = 0xDEADBEEF;
data.y = 42;

int z = data.x;

但我怎么使用无效* 来安全地执行C99型双关?是以下正确的:

But how do I use void * to safely perform type-punning in C99? Is the following correct:

int x = 0xDEADBEEF;

void * helper = (void *)&x;

short *y = (short *)helper;
*y = 42;

int z = x;

我怀疑,code仍然打破严格走样规则,因为在变量内存 X 的地址可以由双方修改 X 和间接引用

I suspect that code will still break the strict aliasing rule since the memory at variable x's address can be modified by both x and a dereferenced y.

如果类型双关是通过未定义的void * ,是什么的无效* 在C99的目的是什么?

If type-punning is undefined via void *, what is the purpose of the void * in C99?

推荐答案

无效* 无关型,双关。它的主要目的是:

void * has nothing to do with type-punning. Its main purposes are:


  1. 要允许通用的分配和释放不关心调用者存放在那里的对象类型的操作(如的malloc 免费)。

要允许呼叫者指针传递给通过一个函数(如的qsort 任意类型,将其传回通过回调和在pthread_create )。在这种情况下,编译器不能执行类型检查;它的你的责任的写作主叫和回调时,以确保回调访问正确类型的对象。

To allow a caller to pass a pointer to an arbitrary type through a function that will pass it back via a callback, (e.g. qsort and pthread_create). In this case, the compiler cannot enforce type checking; it's your responsibility when writing the caller and callback to ensure that the callback accesses the object with the correct type.

指针到无效在一些地方也被用来(如的memcpy ),它实际上是一个对象进行操作重叠的 unsigned char型[] 重新presentation的对象。这可以被看作是类型双关的,但它不是一个别名冲突,因为字符类型允许任何别名来访问其重新presentation。在这种情况下,无符号字符* 也将工作,但无效* 的优点是,指针会自动转换为无效*

Pointers to void are also used in a few places (like memcpy) that actually operate on an object as the overlaid unsigned char [] representation for the object. This could be seen as type-punning, but it's not an aliasing violation because char types are allowed to alias anything to access its representation. In this case, unsigned char * would also work, but void * has the advantage that pointers automatically convert to void *.

在你的榜样,因为原来的类型是 INT ,而不是工会,有输入,双关语和访问它不合法的方式总之。你可以的 X 的值,而不是复制到工会,进行良好定义的类型夯实那里,然后复制回来。一个好的编译器应该完全忽略副本。或者,你可以打破写成字符写和那么这将是合法的别名。

In your example, since the original type is int and not a union, there is no legal way to type-pun and access it as short. You could instead copy the value of x to a union, perform well-defined type-punning there, then copy it back. A good compiler should omit the copy entirely. Alternatively, you could break the write down into char writes and then it would be legal aliasing.

这篇关于键入与void *的双关语不打破严格走样规则在C99的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆