C ++标准在哪里描述了对基元指针的转换?

时间:2013-02-06 13:59:32

标签: c++ casting language-lawyer

在优秀的博文What Every Programmer Should Know About Undefined Behavior中,“违规类型规则”部分说:

  

将一个int *转换为float *并取消引用它(访问“int”就好像它是一个“float”)是未定义的行为。 C要求通过memcpy进行这些类型的转换:使用指针强制转换不正确并导致未定义的行为。对此的规则是非常细微的,我不想在这里详细说明(char *有例外,向量有特殊属性,工会改变事物等)。

我想了解他们完全细微差别的规则。他们在C ++ 11规范中的位置是什么?或者失败了,C规范(C90,C99,C11)?

在从this Stack Overflow question,N3485链接的C ++ 11规范中,我正在查看5.2.10“重新解释强制转换”,但是没有看到char *或联合的例外语言。所以这可能不是正确的地方。那么正确的地方在哪里?

3 个答案:

答案 0 :(得分:4)

您正在寻找的规则是§3.10/ 10(在C ++ 11中):

  

如果程序试图访问对象的存储值   通过以下类型之一以外的glvalue   行为未定义:    - 对象的动态类型,

     

- 对象的动态类型的cv-quali fi ed版本,

     

- 与对象的动态类型相似的类型(如4.4中所定义的),

     

- 与对象的动态类型对应的有符号或无符号类型,    - 对应于动态类型的cv限定版本的有符号或无符号类型   对象,

     

- 聚合或联合类型,包括其元素中的上述类型之一或非静态类型   数据成员(包括,递归地,子集合的元素或非静态数据成员   或包含联盟),

     

- 一种类型,是对象动态类型的(可能是cv-quali fi ed)基类类型,

     

- char或unsignedchar类型。

undefined有不同的类型(或动机) 行为。

如果将int*投射到float*然后再投射 解除引用它,很明显标准无法定义 它,因为可能发生的将取决于架构,和 int的值。另一方面,引用的段落 完全错误 - 使用memcpy进行转换是 也是未定义的行为,原因大致相同。

未定义行为的动机之一是 允许实现以有意义的方式定义它 对于目标体系结构,如果存在。就是这样 一件事。故意使其失败的编译器是 有缺陷的。当然,如果我们假设32位2的补码 int和32位IEEE float,我们可以预期某些值 int对应于捕获NaN,这将导致程序 失败。这是行为的部分原因 不确定的;允许这样的事情发生。但如果我们是 熟悉硬件的低级细节, 应该按预期工作,提供编译器可以看到 演员。 如果没有,这是编译器的QoI问题,等等 对于此类工作,应避免使用编译器。

如上所述,这个特殊情况,事实上,在所有情况下 涉及打字的案件(写给一名成员) 一个联盟,并从另一个人那里读书,确实有姿势 一个问题,标准尚未找到足够的问题 措辞。出现问题的原因通常是编译器 允许假设指向不同类型的指针(除了 字符类型)别别名; int*永远无法指向的人 与float*相同的对象。并证明了两个指针 不能别名对于优化很重要。一个编译器 中断指针转换或联合清晰可见的代码 刚破坏,即使标准说它是未定义的行为。 一个破坏代码的编译器,它所看到的只是两个指针 对于不相关的类型是可以理解的,即使在这种情况下也是如此 标准说行为定义明确。

使用memcpy通过使用两个不同的方法来避免此问题 对象,不用别名。它仍然遇到未定义 行为,因为将int的位模式放入 一个float,然后访问浮动,没有任何定义 行为。 (反之亦然;我知道至少有一台机器在哪里 将float的位复制到int可能会导致 非法int值。)

答案 1 :(得分:1)

C ++标准说如果没有明确地描述某个行为被定义,那么它是隐式未定义的。由于标准没有定义将int*转换为float*的行为,因此隐式未定义。

答案 2 :(得分:0)

关于指针的

reinterpret_cast是根据static_cast指针void定义的

5.2.10重新解释cast [expr.reinterpret.cast]>

  

7可以将对象指针显式转换为对象指针   一种不同的类型。 70当“指向T1的指针”类型的prvalue v为   转换为“指向cv T2的指针”类型,如果T1和T2都是标准布局,则结果为static_cast<cv T2*>(static_cast<cv void*>(v))   类型(3.9)和T2的对齐要求不比更严格   T1的那些,或者如果任何一种类型无效。转换类型的prvalue   “指向T1的指针”到“指向T2的指针”(其中T1和T2为   对象类型以及T2的对齐要求为否   比T1更严格,并回到原来的类型产生   原始指针值。任何其他此类指针的结果   转换未指定。

5.2.9静态演员[expr.static.cast]

  

13类型“指向cv1 void的指针”的prvalue可以转换为a   类型为“指向cv2 T的指针”的prvalue,其中T是对象类型和cv2   与cv1相同的cv-quali fi cation或更高的cv-quali fi cation。   空指针值转换为空指针值   目的地类型。转换为对象的类型指针的值   “指向cv void”并返回,可能具有不同的cv-quali fi cation,   应具有原始价值。