有没有办法避免严格的别名警告?

时间:2014-12-11 22:53:45

标签: c++

我正在使用一个使用回调的库(ENet)。在这些回调函数中,它传递一个结构,其中包含用于用户数据的void *,供您自己使用。我想使用该变量,但不是指针。我不想分配内存,所以我可以指出它,我宁愿直接使用void *的空间来存储size_t。

但是,正如预期的那样,当我将void *变量转换为size_t变量时,我得到一个严格的别名警告。而回调的结构并没有提供一个联合来访问它作为一个非空的东西*。

我知道我可以完全禁用该警告,但我宁愿为这种特殊情况保持沉默。有没有办法编写这种类型的转换,让编译器知道它是故意的,以避免警告?

修改

以下是我尝试做的一个例子。由于我需要能够编辑用户值,因此我将其转换为size_t,同时还尝试获取对它的引用:

size_t& offset = reinterpret_cast<size_t&>(packet->userData);

这样可行,但会发出警告。

1 个答案:

答案 0 :(得分:4)

  

但是,正如预期的那样,当我将void *变量取消引用到size_t变量时,我得到一个严格的别名警告。

如果你想使用void *本身来传输一个普通的整数,你不想取消引用它,你想把它转换成一个合适的整数类型(intptr_t是你最好的选择,因为标准保证它可以通过void *)生存到往返。

intptr_t magic=42;
register_callback(&myfunc, (void *)magic);

// ...

void myfunc(void *context)
{
    intptr_t magic=(intptr_t)context;
    // ...
}

(如果你喜欢C ++风格的演员表,那些都是reinterpret_cast

此外,您可能在代码中做了一些奇怪的事情,因为void *(如char *unsigned char *)不受严格别名规则的约束(它们可以为任何其他指针设置别名)。


<强> 更新

  

以下是我尝试做的一个例子。由于我需要能够编辑用户值,因此我将其转换为size_t,同时还尝试获取对它的引用:

size_t& offset = reinterpret_cast<size_t&>(packet->userData);
     

这样可行,但会发出警告。

不,即使假设size_tvoid *具有相同的大小和对齐要求(无法保证),也无法轻松完成;不允许使用void *&size_t &进行别名(此外,这特别狡猾,因为它隐藏在参考中)。

如果你真的需要这样做,你必须与你的编译器达成协议;例如,在gcc中,您可以使用-fno-strict-aliasing编译只有这个文件的文件,而不是简单地禁用警告(=隐藏地毯下的潜在问题),禁用编译器关于严格别名的假设,即使指向不相关类型的指针/引用指向相同的东西,生成的代码也能正常工作。