function return 改为直接写在printf语句中
function return changed as directly written in printf statement
#include <stdio.h>
#include <math.h>
int main() {
printf("%d\n", pow(3546, 0));
return 0;
}
以上代码打印值0
虽然下面的代码打印值 1
#include <stdio.h>
#include <math.h>
int main() {
int a = pow(3546, 0);
printf("%d\n", a);
return 0;
}
为什么会这样?尽管它们是等价的。
如 this answer 中所述,printf
使用格式说明符知道要从堆栈中弹出什么(%d
是 sizeof(int)
,在我的文件中是 4 个字节系统)。
(编辑: 正如 rici 在评论中指出的那样,它不能保证是堆栈(在 x86
上它在 CPU 大部分时间注册。标准从不讨论实现,这就是这个问题的全部内容。)
一个有趣的小事实:在我的 Windows 10 框中,它是 0 和 1。在我的 Xubuntu VBox 中,它是 1 和 -2132712864。因此,printf
仅弹出 4 个字节,而您机器的字节顺序破坏了结果。来自 pow(3) manual:
#include <math.h>
double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);
因此,为了在这两种情况下都获得正确的结果,请使用 correct printf
format specifier:
double a = pow(3546, 0);
并且:
printf("%lf\n", pow(3546, 0));
如果您想了解更多关于 可变参数函数 (像 printf
这样的函数,它采用可变数量的参数),请先阅读 API manual page.
#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
pow
returns 类型 double
的结果,并且 %d
不是用于格式化它的正确转换说明符。 C 标准未定义由此产生的行为。
要打印 double
,您可以使用 %g
或 %f
,以及其他选项:
printf("%g\n", pow(3456, 0));
printf("%f\n", pow(3456, 0));
在int a = pow(3546,0);
中,double
值自动转换为int
用于初始化int
a
,然后打印int
和 %d
是正确的。
没有对等。后一个函数在打印前明确地将数字转换为 int
,而前一个函数通过尝试使用错误的格式说明符打印浮点数而导致 UB——你很幸运得到 0
,你可能得到了一个任意数字。
请打开编译器上的所有警告,它应该会抱怨对错误的数据类型使用了错误的格式。
#include <stdio.h>
#include <math.h>
int main() {
printf("%d\n", pow(3546, 0));
return 0;
}
以上代码打印值0
虽然下面的代码打印值 1
#include <stdio.h>
#include <math.h>
int main() {
int a = pow(3546, 0);
printf("%d\n", a);
return 0;
}
为什么会这样?尽管它们是等价的。
如 this answer 中所述,printf
使用格式说明符知道要从堆栈中弹出什么(%d
是 sizeof(int)
,在我的文件中是 4 个字节系统)。
(编辑: 正如 rici 在评论中指出的那样,它不能保证是堆栈(在 x86
上它在 CPU 大部分时间注册。标准从不讨论实现,这就是这个问题的全部内容。)
一个有趣的小事实:在我的 Windows 10 框中,它是 0 和 1。在我的 Xubuntu VBox 中,它是 1 和 -2132712864。因此,printf
仅弹出 4 个字节,而您机器的字节顺序破坏了结果。来自 pow(3) manual:
#include <math.h>
double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);
因此,为了在这两种情况下都获得正确的结果,请使用 correct printf
format specifier:
double a = pow(3546, 0);
并且:
printf("%lf\n", pow(3546, 0));
如果您想了解更多关于 可变参数函数 (像 printf
这样的函数,它采用可变数量的参数),请先阅读 API manual page.
#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
pow
returns 类型 double
的结果,并且 %d
不是用于格式化它的正确转换说明符。 C 标准未定义由此产生的行为。
要打印 double
,您可以使用 %g
或 %f
,以及其他选项:
printf("%g\n", pow(3456, 0));
printf("%f\n", pow(3456, 0));
在int a = pow(3546,0);
中,double
值自动转换为int
用于初始化int
a
,然后打印int
和 %d
是正确的。
没有对等。后一个函数在打印前明确地将数字转换为 int
,而前一个函数通过尝试使用错误的格式说明符打印浮点数而导致 UB——你很幸运得到 0
,你可能得到了一个任意数字。
请打开编译器上的所有警告,它应该会抱怨对错误的数据类型使用了错误的格式。