对C ++指针的疑虑很少?

时间:2017-07-17 16:42:21

标签: c++ pointers

我一直在参加编程范例的讲座'斯坦福大学。在那里我遇到了以下代码:

int l = 10;
float m = *(float*)&l;

我知道第一次施法完成然后解除引用。 如何将值分配给m?这种铸件有什么特别之处,即简单铸造就可以通过简单地进行(float)

此投射的特殊之处以及如何将值赋给变量?

注意:此代码可能仅供理论使用,但我想了解其背后的概念。

2 个答案:

答案 0 :(得分:4)

以下声明:

  

*(float*)&l;

使用

  • &地址,
  • *间接和
  • (float*) c-style cast,

运算符。

所有这些运算符在operator precedence列表中排名第3,它们都是从右到左阅读的。

首先,l的地址被采用。接下来,该地址被转换为float*(浮点指针)。最后,使用*取消引用此地址以读取该值。最后一步是未定义的行为。

这是违反strict aliasing rule的未定义行为。它可能会为你制作一杯茶,或者它可能会将这些碎片重新解释为漂浮物。

在我的系统上发生以下情况: 在地址l(小端):

0x000000FC780FFC94  0a 00 00 00

地址m

0x0000004547B5F874  0a 00 00 00

l,解释为int是:10

m,解释为float为:1.401e-44#DEN

此结果(在我的系统上)的原因是intfloat大小相同(msvc 64位上为4个字节),浮点数interpreted from binary 1010为1.401 e-44#DEN:

enter image description here

答案 1 :(得分:1)

首先,警告:根据C ++标准,这是未定义的行为。编译器在执行此行时可以自由地使程序执行任何,并且在许多情况下它不会执行程序员期望的操作。但是,对于那些熟悉C ++的人来说,意图有明确的含义,在大多数情况下,编译器可能这样做。

首先,让我们来看看如果你按预期使用(float)l会发生什么。程序将取l的值,解释为int,并返回具有相同值的浮点数;在这种情况下,那是10.0。这通常是你想要的,并且是完全明确的。

现在,让我们看看你实际拥有的代码:*(float*)&l;。根据此表达式的特定语法,应从右向左阅读。 &l部分表示“获取l存储在内存中的位置”,通常称为“指向l的指针”。由于lint,因此此表达式的类型为“指向int的指针”。

然后,(float*)部分是演员。它说“将指针指向 - int作为指针指向 - float”。这应该是指向内存中相同位置的指针,但是当程序访问它时,它会将该位置的位读取为float

第一个*取消引用此指针指向float,并获取float。这是未定义的部分;该语言假定您不会访问与两种不同类型相同的指针。它被称为“指针别名”,并且根据平台,编译器,优化标志等可以做任何事情。 预期的行为可能是为float提供与int相同的位模式,其值为10.

要了解这意味着什么,我们需要了解floatint在硬件级别的存储方式。 int只是存储为具有相同值的二进制数,some complications为负数。 floatmore complicated,如果floatintendianness存储不同,则会出现更多复杂情况。

f的最可能值是,described by rex,1.4e-44(即负数44的十倍至1.4倍)。如果floatint s具有不同的字节顺序,则另一个合理的值约为6.16e-33。