这是我的代码,我不知道为什么会发生这种情况:
#include <stdio.h>
void foo(float *);
int main()
{
int i = 10, *p = &i;
foo(&i);
}
void foo(float *p)
{
printf("%f\n", *p);
}
输出:
0
答案 0 :(得分:5)
正如已经说过的那样,你将整数变量的地址作为单精度浮点数的地址传递。
理想情况下,应该禁止这种隐式转换,但是根据编译器以及它是干净的C还是C ++,它可能只会导致警告。
但为什么它会完全打印0?
这是因为单精度FPN的方式为represented in memory:
(1 bit of sign)|(8 bits of biased exponent)|(23 bits of significand(mantissa))
二进制10是
0|0000 0000|000 0000 0000 0000 0000 0000 1010
因此,当被解释为浮点值时:
(sign = 0)(biased exponent = 0)(significand = 10)
偏倚指数是正常指数加上127 - http://en.wikipedia.org/wiki/Exponent_bias
要计算我们将使用以下公式的值:
floatValue = ((sign) ? (-1) : (1)) * pow(2, normalExponent) * significand
那会产生:
floatValue = 1 * pow (2, 0 - 127) * 10 = 10 * 2 in pow -127.
这是一个非常小的数字,当使用%f
说明符表示时会转换为"0"
字符串。
<强> SOLUTION:强>
要解决此问题,只需使用临时变量和显式强制转换,然后再调用foo
:
int main()
{
int i = 10;
float temp = (float)i;
foo(&temp);
}
void foo(float *p)
{
printf("%f\n", *p);
}
P.S。为了避免将来出现此类问题,请始终将编译器设置为最高的实际警告级别,并在运行应用程序之前始终处理每个警告。
答案 1 :(得分:1)
因为您要将整数对象和指针对象声明为int
和int *
而不是float
和float *
。
如果没有显式转换,则无法将类型为int *
的对象传递给期望类型为float *
的参数的函数。
变化:
int i = 10, *p = &i;
到
float i = 10, *p = &i;
请注意,p
中的main
指针未被使用,并且可以删除其声明。
答案 2 :(得分:1)
您实际上是将一个指向int的指针转换为指向float的指针。这是合法的,但是BAD- printf试图将为int保留的内存理解为float(在内存中表示不同)并且结果未定义。
答案 3 :(得分:1)
这是因为,您正在将一个Integer传递给一个函数,并且您正在使用float数据类型。
编译时 - 如果启用警告标志 -
,您将收到警告root@sathish1:~/My Docs/Programs# cc float1.c
float1.c: In function ‘main’:
float1.c:11:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
float1.c:3:6: note: expected ‘float *’ but argument is of type ‘int *’
它清楚地告诉你你在做什么。
您的功能超出float *
,但您正在通过int *
。因此,在打印时,它将搜索相应的存储区域并尝试打印它。但浮点变量存储在IEEE 754标准中,但该函数接收整数地址,因此它将尝试在该存储单元中打印数据(int
未存储在IEEE 754标准中)。所以结果是未定义的。
答案 4 :(得分:1)
您尝试读取分配给int类型变量的区域,并尝试读取为float。
浮点数被写为尾数和指数。根据记忆中的表示,您可能会使用&#34; 10&#34;加载指数。尾数保持为零。结果,0 ^ 10(或者它被解释)是0。
答案 5 :(得分:0)
您正在调用函数,期望float*
带有指向int的指针。在C ++中,这是一个错误,您的代码无法编译。在C中,你很可能会得到一个警告和未定义的行为。