GCC中的尾部递归无回报陈述
显然,以下代码在GCC中起作用。我在在线GDB
中尝试了该代码。
# include <stdio.h>
int calc_gcd (int a, int b) {
int r = a % b;
if (r == 0) {
return b;
} else {
calc_gcd (b, r);
}
}
int main() {
int a, b, gcd, dividend, divisor;
printf ("Enter two numbers: ");
scanf ("%d%d", &a, &b);
dividend = (a > b) ? a : b;
divisor = (a < b) ? a : b;
gcd = calc_gcd (dividend, divisor);
printf ("GCD = %d\n", gcd);
return 0;
}
但是它在clang 13
中失败,以下结果
tail_recursion_gcd.c:15:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
}
^
1 warning generated.
Enter two numbers: 15 10
GCD = 127 // garbage
我没有得到。显然,GCC允许的不直观,您必须从功能中返回。
我已经尝试了以下操作,但是在GCC中不起作用,
# include <stdio.h>
int useless_func()
{
3050;
}
int main() {
printf("result = %d", useless_func());
return 0;
}
输出为结果= 0
Apparently the following code works in GCC. I tried that code in onlinegdb
.
# include <stdio.h>
int calc_gcd (int a, int b) {
int r = a % b;
if (r == 0) {
return b;
} else {
calc_gcd (b, r);
}
}
int main() {
int a, b, gcd, dividend, divisor;
printf ("Enter two numbers: ");
scanf ("%d%d", &a, &b);
dividend = (a > b) ? a : b;
divisor = (a < b) ? a : b;
gcd = calc_gcd (dividend, divisor);
printf ("GCD = %d\n", gcd);
return 0;
}
But it fails in clang 13
with following results
tail_recursion_gcd.c:15:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
}
^
1 warning generated.
Enter two numbers: 15 10
GCD = 127 // garbage
I'm not getting it. Clearly what GCC allows isn't intuitive, you have to return from a function.
I've tried the following but that doesn't work in gcc
# include <stdio.h>
int useless_func()
{
3050;
}
int main() {
printf("result = %d", useless_func());
return 0;
}
The output is result = 0
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
TL; DR:您的老师给您的GCD功能是无法便携的。
您想要的是什么:
您正在使用哪种版本的海湾合作委员会,以及在哪种操作系统上?
GCC比Clang更宽大。 GCC看来决定函数
Calc_gcd
不应该失败,并且应该返回Calc_gcd(B,R)
的结果。当您使用Clang编译时,我很惊讶它没有返回
1
。当我在M1 MacBook Pro上编译时确实如此。来自在这里:
在x86_64 linux上,当调用非空隙值的函数时,将空间分配在堆栈上的返回值。因此,在没有明确的返回语句的情况下,仍然返回一些值。
注意:在X86_64上,返回值存储在RAX中(EAX是较低的位)。
我在X86_64 Ubuntu Server上使用GCC 7.5.0编译了18.04。
我使用的命令是
gcc -o gcd gcd.c -no -pie -g
。的汇编转储
这是
calc_gcd
:和Clang 6.0.0:您可以看到编译器在优化方面做出了不同的选择。
实际上,使用GCC,
RBP-0x18
等于0x00000005
by +38。使用Clang,
RBP-0x4
等于完全不同的东西。在我的计算机上,在pwndbg中,它是0x00007fff
。TL;DR: The GCD function your teacher gave you is not portable.
What you want follows:
What version of GCC are you using, and on what operating system?
GCC is much more lenient than Clang. It looks like GCC decided that the function
calc_gcd
shouldn't fail and should return the result ofcalc_gcd(b, r)
.When you compiled with Clang, I'm surprised that it didn't return
1
. It did when I compiled on an M1 MacBook Pro.From here:
On x86_64 Linux, when a function that returns a non-void value is called, space is allocated on the stack for the return value. Thus, with no explicit return statement, some value is still returned.
Note: on x86_64, the return value is stored in RAX (EAX is the lower bits).
I compiled with GCC 7.5.0 on x86_64 Ubuntu Server 18.04.
The command I used was
gcc -o gcd gcd.c -no-pie -g
.Here's the assembly dump for
calc_gcd
:And with Clang 6.0.0:
You can see that the compilers made different choices in optimizations.
In fact, with GCC,
rbp-0x18
is equal to0x00000005
by +38.With Clang,
rbp-0x4
is equal to something entirely different. On my machine, in pwndbg, it was0x00007fff
.您的代码被错误。它可以从
int
函数返回而不返回值的情况下仅消耗该值。这是K&amp; RC的保留,不再使用。显然不正确。你想要。
实际上,此特定代码倾向于在
-O0
上使用,因为返回值在寄存器中剩下的是您想要的返回值。Your code is bugged. It is allowed to return from an
int
function without returning a value only if the value will never be consumed. This is a holdover from K&R C that should no longer be used.Clearly incorrect. You want.
In fact this specific code tends to work at
-O0
because the return value is left over left over in the register is the return value you want.