严格走样C或C ++的事情吗? [英] Is strict aliasing is c or c++ thing?

查看:117
本文介绍了严格走样C或C ++的事情吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ISO / IEC 9899:TC2,标准说,以下


  

6.3.2.3指针


  
  

      
  1. 的指针的对象或不完整的类型可被转换成一个指针到一个不同的
      对象或不完全类型。如果得到的指针是不正确的指向的类型一致,行为定义理解过程网络。否则,再转换回时,其结果应比较等于原始指针。时的指针的对象被转换为指针为字符类型,则结果点到最低寻址的字节
      物体。结果的连续增量,直至对象的大小,收率指针对象的剩余字节。

  2.   

因此​​,它不是从标准明确表示一种类型的指针可以浇铸到另一种类型的指针。


解决方案

严格别名规则定义其他地方。这是写法:

C(ISO / IEC 9899:1999 6.5 / 7):


  

对象应具有其存储的价值只能通过左值访问
  具有下列类型之一前pression:


  
  

      
  • 一个类型的有效对象的类型,
  • 兼容
      
  • 一个合格网络版版型与有效类型兼容
      对象,

  •   
  • 一类型,它是符号或对应于该无符号类型
      有效类型的对象,

  •   
  • 一类型,它是符号或对应于无符号类型
      有效对象的类型的合格网络版版本,

  •   
  • ,包括上述之一的聚集或联合类型
      其成员(包括递归的成员之间的类型
      子聚集或包含的联合),或

  •   
  • 字符类型。

  •   

C ++(ISO / IEC 14882:2011 3.10 [basicl.lval] / 15):


  

如果程序尝试通过访问对象的存储值
  的以外的以下类型的行为是一个左值
  未定义:


  
  

      
  • 的动态类型的对象,

  •   
  • 的动态类型对象的CV-合格的版本,

  •   
  • 相似(如在4.4定义)的动态的对象的类型,
  • 一类型
      
  • 一类型,它是符号或对应于该无符号类型
      动态类型的对象,

  •   
  • 一类型,它是符号或对应于无符号类型
      动态类型对象的CV-合格的版本,

  •   
  • ,包括上述之一的聚集或联合类型
      其元件或非静态数据成员(包括之间的类型,
      递归,一个元件或子聚集的非静态数据成员
      或含有工会),

  •   
  • 一个类型,是一个(可能CV-限定)基类类型
      动态类型的对象,

  •   
  • 字符 unsigned char型键入

  •   


C标准不从铸造指针无关类型禁止你,只要没有排成一条直线的问题。然而,由于严格别名规则,你基本上无法提领从这样的投获得的指针。所以,做这种无效指针唯一有用的就是将它转换回正确的类型(或兼容型)。

这主要是在C ++一样用reinter pret_cast(5.2.10 [expr.reinter pret.cast] / 7):


  

的对象的指针可以显式转换为不同类型的对象的指针。当prvalue v 类型的指针 T1 转换为类型指针的 CV T2 ,结果是的static_cast&LT; CV T2 *&GT;(的static_cast&LT; CV无效*&GT;(五))如果两个 T1 T2 是标准的布局类型(3.9)和<$的对齐要求C $ C> T2 并不比那些 T1 的严格,或者这两个类型是无效。转换类型的prvalue指针 T1 的类型指针 T2 (其中 T1 T2 的对象类型和其中 T2 的对齐要求没有比那些 T1 ),并恢复到原来的类型产生原始指针值更为严格。任何其他这样的指针转换的结果是不确定的。


In ISO/IEC 9899:TC2, the standard says following

6.3.2.3 Pointers

  1. A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

So, it is not clear from the standard that a pointer of one type can be casted to pointer of another type.

解决方案

Strict aliasing rule is defined somewhere else. This is the wording:

C (ISO/IEC 9899:1999 6.5/7):

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:

  • a type compatible with the effective type of the object,
  • a qualified version of a type compatible with the effective type of the object,
  • a type that is the signed or unsigned type corresponding to the effective type of the object,
  • a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
  • an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
  • a character type.

C++ (ISO/IEC 14882:2011 3.10 [basicl.lval] / 15):

If a program attempts to access the stored value of an object through an lvalue of other than one of the following types the behavior is undefined:

  • the dynamic type of the object,
  • a cv-qualified version of the dynamic type of the object,
  • a type similar (as defined in 4.4) to the dynamic type of the object,
  • a type that is the signed or unsigned type corresponding to the dynamic type of the object,
  • a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
  • an aggregate or union type that includes one of the aforementioned types among its elements or non-static data members (including, recursively, an element or non-static data member of a subaggregate or contained union),
  • a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
  • a char or unsigned char type.


The C standard doesn't prohibit you from casting the pointer to an unrelated type, provided there are no allignment problems. However, due to the strict aliasing rule, you basically can't dereference a pointer obtained from such a cast. So the only useful thing to do with such "invalid" pointer is to cast it back to the correct type (or a compatible type).

It's mostly the same in C++ with reinterpret_cast (5.2.10 [expr.reinterpret.cast] / 7):

An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of type "pointer to T1" is converted to the type "pointer to cv T2", the result is static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.

这篇关于严格走样C或C ++的事情吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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