使用 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 的历史,float
到 printf
的参数被作为 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
)
当我 运行 此代码在第一个 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 的历史,float
到 printf
的参数被作为 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
)