c++ - 我是否正确理解 C/C++ 严格别名?

标签 c++ c strict-aliasing

我读过 this article about C/C++ strict aliasing .我认为这同样适用于 C++。

据我了解,严格别名用于重新排列代码以实现性能优化。这就是为什么两个不同(在 C++ 情况下不相关)类型的指针不能引用相同的内存位置。

这是否意味着只有修改内存才会出现问题?除了可能的问题with memory alignment .

例如,处理网络协议(protocol),或反序列化。我有一个字节数组,动态分配并且数据包结构正确对齐。我可以reinterpret_cast 它到我的数据包结构吗?

char const* buf = ...; // dynamically allocated
unsigned int i = *reinterpret_cast<unsigned int*>(buf + shift); // [shift] satisfies alignment requirements

最佳答案

这里的问题不是严格的别名,而是结构表示要求。

首先,在charsigned charunsigned char任何 之间使用别名是安全的其他类型(在您的情况下,unsigned int。这允许您编写自己的内存复制循环,只要它们是使用 char 类型定义的。这是由 C99 (§6.5) 中的以下语言授权:

 6. The effective type of an object for an access to its stored value is the declared type of the object, if any. [Footnote: Allocated objects have no declared type] [...] If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.

 7. An object shall have its stored value accessed only by an lvalue expression that has one of the following types: [Footnote: The intent of this list is to specify those circumstances in which an object may or may not be aliased.]

  • a type compatible with the effective type of the object,
  • [...]
  • a character type.

类似的语言可以在 C++0x 草案 N3242 §3.11/10 中找到,尽管在分配对象的“动态类型”时并不清楚(我希望能进一步引用动态是什么type 是一个 char 数组,POD 对象已作为具有适当对齐方式的 char 数组复制到该数组。

因此,别名在这里不是问题。然而,严格阅读该标准表明,C++ 实现在选择 unsigned int 的表示形式方面具有很大的自由度。

作为一个随机示例,unsigned int 可能是一个 24 位整数,用四个字节表示,其中散布着 8 个填充位;如果这些填充位中的任何一个与某个(常量)模式不匹配,它就会被视为陷阱表示,并且取消引用指针将导致崩溃。这是一个可能的实现吗?也许不是。但是从历史上看,系统有奇偶校验位和其他奇怪的东西,因此直接从网络读取到 unsigned int通过严格阅读标准,是不是犹太洁食。

现在,填充位的问题在当今大多数系统上主要是一个理论问题,但值得注意。如果你打算坚持使用 PC 硬件,你真的不需要担心它(但不要忘记你的 ntohl - endianness 仍然是一个问题!)

当然,结构使情况变得更糟 - 对齐表示取决于您的平台。我曾在一个嵌入式平台上工作,其中所有类型的对齐方式均为 1 - 结构中从未插入任何填充。在多个平台上使用相同的结构定义时,这可能会导致不一致。您可以手动计算出数据结构成员的字节偏移量并直接引用它们,或者使用特定于编译器的对齐指令来控制填充。

因此,从网络缓冲区直接转换为 native 类型或结构时必须小心。但在这种情况下,别名本身不是问题。

关于c++ - 我是否正确理解 C/C++ 严格别名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7321513/

相关文章:

c - 严格别名违规 : Why gcc and clang generate different output?

c++ - 使用 static_cast 将任何指针转换到 char 指针

c++ - 模拟窗口之间的鼠标选择消息

c++ - 使用 zlib 压缩文件而不保存到磁盘并通过套接字发送

c++如何创建仿函数的std::vector

c - 空指针取消引用未初始化的内存是否属于内存损坏

c++ - map 初始化 : object code is 50 times larger than source code

c - 为什么在c中初始化n维数组时必须显式指定n-1维

c - [ ] 也是 C 中的声明符(在参数声明中使用时)吗?

c++ - 为您的 C++ 库和严格的别名提供 C API