使用 printf 使用 %d 打印浮点指针

Using printf to print float pointer using %d

当我 运行 此代码在第一个 printf 中打印 a 的地址,在第二个 printf 中打印 a 的值。

#include <stdio.h>
int main() 
{
float a=7.999999;
float *b,*c;
b=&a;
c=b;
printf ( "\n%u %u %u", &a, b, c );
printf ("\n%f %f %f %f",a,*( &a ),*b,*c );
}

但是当我像这样在第二个 printf 中将 %f 更改为 %d 时。

#include <stdio.h>   
int main() 
{
float a=7.999999;
float *b,*c;
b=&a;
c=b;
printf ( "\n%u %u %u", &a, b, c );
printf ("\n%d %d %d %d",a,*( &a ),*b,*c );
}

它在第二个 printf 中打印随机值,请解释原因。 应该使用 %f 打印浮点指针,但为什么不能使用 %d。

why float pointer should be printed using %f but why can't by using %d.

转换规范(%d%f)告诉 printf 两件事:

  • 在哪里可以找到传递的参数。
  • 如何解释该参数的位。

关于第一点,现代处理器通常对整数数据和浮点数据有不同的寄存器。由于这个和相关的原因,关于如何将参数传递给子例程(计算环境的应用程序二进制接口的一部分)的规则通常说前几个整数参数在某些整数寄存器中传递,而前几个浮点参数在浮点寄存器中传递。 (在前几个参数之后,通常会在硬件堆栈上传递其他参数。)

所以,当你告诉 printf%d 转换一个数字但传递给它一个浮点参数时,printf 可能会从一些整数寄存器中获取值,但是浮点参数不存在。它在一些浮点寄存器中。然后 printf 打印出错误的值。

关于第二点,整数和浮点数的值的编码方式不同。 %d 告诉 printf 将这些位解释为二进制数(以及一些表示负数的方案,最常见的是二进制补码)。 %f 告诉 printf 将这些位解释为具有浮点格式的数字编码。此外,由于 C 的历史,floatprintf 的参数被作为 double 传递。 double 最常见的浮点格式使用 1 位作为符号,11 位作为 2 的指数,52 位作为 significand 部分。 (在普通的科学记数法中,对于数字-3.74•1013,-是符号,13是指数,3.74是尾数。)如果printf确实取编码 double 并根据 %d 解释它们的部分或全部位将打印出与浮点数的值非常不同的数字(除非是极其罕见的巧合)。

另请注意,printf ("\n%d %d %d %d",a,*( &a ),*b,*c ); 中未打印或传递任何指针。 a*( &a )*b*c都是a.

printf ( "\n%u %u %u", &a, b, c );中,指针打印不正确。正确的代码是 printf("%p %p %p\n", (void *) &a, (void *) b, (void *) c);。这里我做了三处改动:

  • %p 是打印指针的正确转换规范。有时使用 %u 打印会打印相同的值(虽然是十进制而不是十六进制),但是,如果发生这种情况,那只是因为指针在与 unsigned int 相同的位置传递,它们是相同的大小,并且错误与编译器优化没有冲突。
  • 指针被转换为 void * 用于打印。这确保它们采用通用形式,适用于 %p,在通过时。
  • 我将 \n 移到了字符串的末尾而不是开头。 C 设计用于将换行符放在行尾而不是行首,因为当有换行符时,它会立即将输出发送到交互式设备,而不是将其保存在缓冲区中。

%d REQUIRES 参数是一个 int 值。 (这就是你得到垃圾的原因)

如果您想将浮点数打印为整数,请改用 %0.0f。这将打印四舍五入到最接近的整数的值,并且没有小数(我现在不确定是否打印小数点,但如果是,请尝试替代方案 %0.0g