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

And*_*hko 6 c c++ strict-aliasing

我读过这篇关于C/C++严格别名的文章.我认为同样适用于C++.

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

这是否意味着只有在修改内存时才会出现问题?除了内存对齐可能存在的问题.

例如,处理网络协议或反序列化.我有一个字节数组,动态分配和数据包结构正确对齐.我reinterpret_cast可以使用我的数据包结构吗?

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

bdo*_*lan 7

这里的问题不是严格的混叠,而是结构表示要求.

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

 6.访问其存储值的对象的有效类型是对象的声明类型(如果有).[脚注:分配对象没有声明的类型] [...]如果一个值被拷贝到一个对象具有使用的memcpy或的memmove没有声明的类型,或者被复制为字符类型的数组,则有效类型的修改的对象的对于该访问以及对于不修改该值的后续访问,是从中复制值的对象的有效类型(如果有).对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型.

 7.对象的存储值只能由具有以下类型之一的左值表达式访问:[脚注:此列表的目的是指定对象可能或可能没有别名的情况.]

  • 与对象的有效类型兼容的类型,
  • [...]
  • 一个字符类型.

类似的语言可以在C++ 0x草案N3242§3.11/ 10中找到,虽然在分配对象的"动态类型"时并不是很清楚(我很欣赏有关动态类型的更多参考)一个char数组,POD对象已被复制为具有正确对齐的char数组.

因此,混叠在这里不是问题.但是,严格阅读标准表明C++实现在选择表示形式时有很大的自由度unsigned int.

作为一个随机的例子,unsigned ints可能是一个24位整数,用四个字节表示,其中散布着8个填充位; 如果这些填充位中的任何一个与某个(常量)模式不匹配,则将其视为陷阱表示,并且取消引用指针将导致崩溃.这可能是实施吗?也许不是.但已经有,在历史上,具有奇偶校验位和其它奇怪,并从网络中,以便直接读取到系统unsigned int,通过标准的严格读数,是不洁净.

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

当然,结构使情况更糟 - 对齐表示取决于您的平台.我曾在嵌入式平台中所有类型为1的排列上-没有填充,不断插入结构.在多个平台上使用相同的结构定义时,这可能导致不一致.您可以手动计算数据结构成员的字节偏移量并直接引用它们,也可以使用特定于编译器的对齐指令来控制填充.

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

  • 我认为创建一个对不同类型的指针的`char*`引用是安全的,但不是相反. (3认同)