C 函数返回更改为直接写入printf语句

C 函数返回更改为直接写入printf语句,c,function,printf,pow,C,Function,Printf,Pow,为什么会这样?即使它们是等效的。如中所述,printf使用格式说明符知道从堆栈中弹出什么(%d是sizeof(int),在我的系统中是4个字节) (Edit:正如评论中所指出的,它不能保证是堆栈(在x86上,它大部分时间都在CPU寄存器中)。该标准从不谈论实现,这就是问题所在。) 一个有趣的小事实:在我的Windows10框中是0和1。在我的Xubuntu VBox中,它是1和-2132712864。因此,printf只会弹出4个字节,而您的机器的尾端会扭曲结果。发件人: 以及: 如果您想了解

为什么会这样?即使它们是等效的。

如中所述,
printf
使用格式说明符知道从堆栈中弹出什么(
%d
sizeof(int)
,在我的系统中是4个字节)

Edit:正如评论中所指出的,它不能保证是堆栈(在
x86上,它大部分时间都在CPU寄存器中)。该标准从不谈论实现,这就是问题所在。)

一个有趣的小事实:在我的Windows10框中是0和1。在我的Xubuntu VBox中,它是1和-2132712864。因此,
printf
只会弹出4个字节,而您的机器的尾端会扭曲结果。发件人:

以及:


如果您想了解更多关于可变函数的信息(如
printf
,它接受可变数量的参数),请从阅读开始

#包括
无效VAU开始(VAU列表ap,最后一个);
类型va_arg(va_列表ap,类型);
无效VAU结束(VAU列表ap);
作废VAU副本(VAU列表目的地、VAU列表src);

pow
返回类型为
double
的结果,
%d
不是用于格式化该结果的正确转换说明符。C标准没有定义结果行为

要打印双精度
,您可以使用
%g
%f
,以及其他选项:

#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);

inta=pow(3546,0)
双精度
值自动转换为
int
,用于初始化
int
a
,然后用
%d
打印
int
是正确的。

没有等效项。后一个函数在打印之前显式地将数字转换为
int
,而前一个函数通过尝试使用错误的格式说明符打印浮点数字来生成UB——幸运的是,您得到了
0
,您可能得到了任意数字


请打开编译器上的所有警告,它会抱怨对错误类型的数据使用了错误的格式。

这有帮助吗?第二个代码不会编译,因为有一个小的输入错误,否则我们需要更多关于编译器和编译器标志的信息来帮助您。我们能得到的唯一提示是pow的结果隐式类型化为什么类型的整数。即使是这样,大多数优化程度最低的编译器也会看到pow表达式是常量,并在编译过程中进行转换。第一个是未定义的行为,这意味着任何事情都可能发生(并且不要求一致性)。引用的答案并非普遍正确,因为使用堆栈传递参数不需要函数调用。事实上,在x86上,只有当有相当多的参数时才使用堆栈。参数通常在寄存器中传递,关键是:整数和浮点数进入不同的寄存器。@rici是的,这是正确的。然而,为了简单起见,我认为这是回答一个简单问题的最佳方式。有足够的链接让好奇的头脑扩展自己,伊姆霍。您对如何在保持简单性的同时改进这一点有什么建议吗?实际上,他们都坚持使用堆栈。但是C标准本身从来没有提到堆栈。我知道这听起来像是一个技术性的问题,但知道它还是有点有用的。老实说,我不知道好奇的人会在哪里找到这种联系,尽管我过去也尝试过。引入一个答案中不必要的概念怎么简单?核心概念是,
%d
打印
pow
double
结果是错误的,
%lf
是正确的。那么说,第二个版本之所以有效,是因为
inta=pow(3456,0)
pow
double
结果转换为
int
,然后
printf
正确使用
%d
打印
int
。不要把初学者扔进变量参数特性中;“这些会让他们感到困惑。”埃里克说得不对。编译时转换比
printf
转换做得更好,这是因为实现细节,而不是因为转换。两者都是
double
->
int
。在这两种情况下都是UB,因为您依赖于实现。后一种代码既不包含任何强制转换,也不显式转换。强制转换是
(类型)操作数形式的运算符。在
inta=pow(3456,0),没有强制转换,也没有显式转换。由于C标准中的规则,转换是隐式的;代码中没有明确说明这一点。(这里的显式
int
说明了隐式用于转换的
a
;类型。)@chqrlieforyellowblockquotes:我怀疑其中一个是不满参与者的报复性投票。另一个我不知道。我一般不担心。我不是在为积分做贡献,我有足够多的真实世界积分,想象中的互联网积分不值得关注。我致力于分享好的信息并专注于此。是的,我在同一页上。。。顺便问一下,1975年你用Fortran编写了什么样的计算机?我在那年9月开始:)@chqrlieforyellowblockquotes:一些IBM机器,但我不确定是哪一台。360系统?
#include <stdio.h>
#include <math.h>

int main() {
    int a  = pow(3546, 0);
    printf("%d\n", a);
    return 0;
}
#include <math.h>

double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);
double a = pow(3546, 0);
printf("%lf\n", pow(3546, 0));
#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);
printf("%g\n", pow(3456, 0));
printf("%f\n", pow(3456, 0));