为什么我的函数打印"0"?

Why does my function print '0'?

本文关键字:打印 我的 函数 为什么      更新时间:2023-10-16

这是我的代码,我不知道为什么会发生这种情况:

#include <stdio.h>
void foo(float *);
int main()
{
    int i = 10, *p = &i;
    foo(&i);
}
void foo(float *p)
{
    printf("%fn", *p);
}

输出:

0

正如已经说过的,你正在传递一个整型变量的地址作为单精度浮点数的地址。

理想情况下,这种隐式转换应该是不允许的,但根据编译器以及它是干净的C还是c++,它可能只会导致警告。

但是为什么它打印的是0呢?

这是因为单精度FPN在内存中的表示方式:

(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"字符串。

解决方案:

要解决这个问题,只需在调用foo之前使用临时变量和显式强制转换:
int main()
{
    int i = 10;
    float temp = (float)i;
    foo(&temp);
}
void foo(float *p)
{
    printf("%fn", *p);
}

注:为避免将来出现此类问题,请始终将编译器设置为最大实际警告级别,并始终在运行应用程序之前处理每个警告。

因为您正在声明您的整数对象和指针对象为intint *而不是floatfloat *

如果不进行显式转换,就不能将int *类型的对象传递给需要float *类型参数的函数。

改变:

  int i = 10, *p = &i;

  float i = 10, *p = &i;

请注意,main中的p指针没有被使用,它的声明可以被删除。

实际上是将int型指针转换为float型指针。这是合法的,但是不好——printf试图理解为int保留的内存作为浮点数(它在内存中的表示方式不同),结果是未定义的。

您尝试读取分配给int类型变量的区域,并尝试将其读取为float

浮点数写成尾数和指数。根据内存中的表示,很可能您正在用"10"加载指数,而尾数仍然为零。因此,0^10(或者不管怎么解释)是0。

这是由于,你正在传递一个整数给一个函数,你正在捕捉浮点数据类型。

当你编译它时-如果你启用了警告标志,你会得到警告-

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标准中)。结果是Undefined

您正在调用函数期望float*与指针int。在c++中,这是一个错误,您的代码无法编译。在C语言中,你很可能得到一个警告和未定义的行为。