当我运行此代码时,它会打印第一个 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 );
}
Run Code Online (Sandbox Code Playgroud)
但是当我像这样在第二个 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 );
}
Run Code Online (Sandbox Code Playgroud)
它在第二个 printf 中打印随机值,请解释原因。浮点指针应该使用 %f 打印,但为什么不能使用 %d 打印。
\n\n为什么浮点指针应该使用 %f 打印,但为什么不能使用 %d 打印。
\n
转换规范 (%d或%f) 说明了printf两件事:
关于第一点,现代处理器通常对整数数据和浮点数据具有不同的寄存器。由于这个原因和相关原因,参数如何传递到子例程(计算环境的应用程序二进制接口的一部分)的规则通常规定前几个整数参数在某些整数寄存器中传递,前几个浮点参数在浮点寄存器中传递。(在前几个参数之后,通常会在硬件堆栈上传递其他参数。)
\n因此,当您告诉printf使用转换数字%d但向其传递浮点参数时,printf可能会从某个整数寄存器中获取值,但浮点参数不存在。它在一些浮点寄存器中。然后printf打印错误的值。
关于第二点,整数和浮点数的值以不同的位编码。%d告诉printf将这些位解释为二进制数(以及一些表示负数的方案,最常见的是两个\xe2\x80\x99s补码)。%f告诉printf将这些位解释为具有浮点格式的数字编码。另外,由于 C 的历史,float参数 被printf作为 传递double。最常见的浮点格式double使用 1 位表示符号,11 位表示 2 的指数,52 位表示尾数部分。(在普通科学记数法中,对于数字 \xe2\x88\x923.74\xe2\x80\xa210 13, \xe2\x88\x92 是符号,13 是指数,3.74 是有效数。printf)编码 adouble并根据 解释它们的部分或全部位%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 设计为将换行符放在行尾而不是行首,因为当存在换行符时,它会立即将输出发送到交互设备,而不是将其保存在缓冲区中。