我有这样的代码:
double x = 100.1;
double y;
int *p;
p = (int *) &x;
y = *p;
cout << "y value is: " << y << endl;
我知道这是错误的,我们得到4个字节而不是8个字节。我也知道浮动数字在内存中有一些棘手的表现(但不知道如何),但这个脚本给了我这样的输出:
y value is: 1.71799e+09
据我所知,浮点数也很有价值。我的指针是int,我也期望int结果。为什么不呢?我应该读懂什么?
答案 0 :(得分:6)
我的指针是int,我也期望int结果。为什么不呢?
因为y
是double,而不是int。现在,如果你的意思是问为什么y
没有一个整数值,因为它应该是一个int(必须*有一个整数值)转换为double的结果,看一看输出如下:
std::cout << "y value is: " << std::fixed << y << '\n';
您应该看到的输出是:
y value is: 1717986918.000000
因此,y
具有整数值,您只需使用科学记数法将其打印出来。如果你想知道为什么y
具有这个特定的积分值,那是因为那是*p
的值。
std::cout << "*p is: " << *p << '\n';
*p is: 1717986918
如果您要查看x
的内存转储,其值为100.1
,您会看到:
66 66 66 66 66 06 59 40
当你以int形式访问它时,你得到66 66 66 66
,转换为十进制,是1717986918。
另外需要注意的是,C ++不能保证这一点。实际上,您的程序实际上并不合法,因为当您通过指向int的指针访问double x
时,您违反了别名规则。您的程序可以合法并获得相同的结果,但C ++没有指定浮点值的表示,因此特定的积分值可能在法律上有所不同。
我应该阅读哪些内容?
这是一篇与浮点数表示相关的文章:http://ridiculousfish.com/blog/posts/float.html
C ++没有指定浮点数的表示方式,但大多数C ++实现都使用IEEE-754,因此您也可以查看该规范。这是维基百科页面的开头:https://en.wikipedia.org/wiki/IEEE_floating_point
要了解C ++的别名规则,您可以找到并阅读规范。 IIRC第3.10 / 10节中涉及严格混叠。在SO上还有很多关于别名的问题和答案。
答案 1 :(得分:4)
1.71799e+09
是整数1,717,99x,xxx的浮点表示。
答案 2 :(得分:4)
我的指针是int,我也期望int结果。为什么不呢?
您的指针 int *
, 获得int
结果。
但那并不是你所展示的。您显示的y
是double
。
1.71799e+09
是您获得的int
的双重表示。
答案 3 :(得分:3)
当你这样做时
y = *p;
变量 y 采用 p 指向的 int ,然后将其转换为double。
假设sizeof(double)
为8,sizeof(int)
为4
执行x = 100;
您将double
值100放在 x 中的8个字节上。然后当你执行y = *p;
时,你只能使用8个字节中的4个作为 int 值,然后将该数字转换为 double 。
double 和 int 的二进制格式不同。例如。 100 double 与100 int 的表示方式不同(更不用说大小差异,例如8 vs 4)。
答案 4 :(得分:3)
double x = 100.1;
double y;
int *p;
p = (int *) &x;
// Set a pointer of type integer to point at a floating point. Better C++ style
// would be p = reinterpret_cast<int *>(&x);
// which explains more clearly what you are doing - reinterpreting the pointer as
// a different type.
y = *p;
// *p is an integer. So y is set to the value of *p, which is some crazy
// integer value formed from the interpretation of a double as integer.
cout << "y value is: " << y << endl;
请参阅上面代码中的注释。您正在指向不同类型的数据的指针,然后想知道为什么转换的二进制数字不代表它最初表示的...
(从技术上讲,这段代码违反了有关别名的规则 - 基本上,你为了两个不同的目的使用相同的内存,编译器没有义务在这种情况下“做正确的事” - 我怀疑它在这种特殊情况下会做出你能想到的事情 - 如果你期望的是你得到一个由double的四个第一个字节表示的整数值,那就是)。
如果您希望y
实际包含x
中数字的整数表示,则需要:
y = (int)x;
我们没有明智的方法可以使用指针来进行此转换。
答案 5 :(得分:0)
当您运行以下行时,您将触发未定义的行为:
p = (int *) &x;
一旦你触发了未定义的行为,你的问题的其余部分就毫无意义,因为关于未定义行为的推理没有意义(尽管看看你的其余问题,可能是这一点未定义的行为不会影响你真正的问题。我不确定。)
答案 6 :(得分:-1)