所以当我遇到这段C代码时,我正准备在印度参加入学考试
#include <stdio.h>
int main(void) {
static int i = 4;
if (--i) {
main();
printf("%d", i);
}
}
Run Code Online (Sandbox Code Playgroud)
我认为printf语句永远不会被执行,输出将是空白的.但我看到答案是0000,并且这是由于static关键字与int.
谁能解释为什么printf执行或者那个人错了?
Cor*_*pto 29
在关于递归的问题的上下文中,它将打印出"000"(我不知道为什么答案显示4个零,因为' - i'减量在分配之前发生).如果您展开您获得的电话:
if (--i) { //i == 3
if (--i) { //i == 2
if (--i) { //i == 1
if (--i) { //i == 0
// rest does not get evaluated since the condition is false
}
printf("%d", i); // i is 0 now
}
printf("%d", i); //i is still 0
}
printf("%d", i); //i is still 0
}
Run Code Online (Sandbox Code Playgroud)
但是大多数人都提到这个代码很糟糕,我建议你永远不要考虑你编写的任何软件的这种程度的邋iness.
And*_*dyG 22
它是合法的递归上main用C *(但为什么你会?)
此外,C11(5.1.2.2.1)规定:
它应定义为返回类型
int... [或]如果返回类型不兼容int,则返回到主机环境的终止状态未指定.
(C++声明返回类型必须是int)
所以代码的这部分实际上是符合标准的,但实际的返回是实现定义的(感谢@chux)
谁能解释为什么printf执行或者那个人错了?
如果你用C++编译器编译C,那就错了.否则代码将编译.
现在这已经不在了,printf意志确实会执行,因为static变量只被初始化一次,如6.2.4/3所示
使用存储类说明符声明标识符的对象
static具有静态存储持续时间.它的生命周期是程序的整个执行,它的存储值只在程序启动之前初始化一次
*在C++中绝对不合法.从[basic.start.main]:"函数main不得在程序中使用".这个答案中有很多C++,因为这个问题最初标记为C++,而且信息很有用
mdf*_*t13 13
谁能解释为什么printf执行或者那个人错了?
因为main回报.
这个答案写出了逻辑,但我看到你仍然在评论中提出这个问题.所以我将以不同的方式说同样的事情,并希望你更清楚.
因为变量是static在第一次调用之前声明变量并设置为4.因为它是static,每次都会使用相同的变量.如果再次调用它,它只是跳过声明和初始化(或者甚至可能是第一次,因为static变量可以在运行之前分配).
在第一次调用中,变量递减到3. 3是一个真值,所以我们做了块if.这main递归调用.
在第二次调用中,变量递减到2. 2在C中仍然是真实的.我们main再次递归调用.
在第三次调用中,变量递减为1. 1仍然是真实的.我们main再次递归.
在第四次调用中,变量递减为0. 0在C中为假.我们不进入该块if.我们不会递归.我们不打印.在这次电话会议中没有什么可做的main.它最后返回.
现在我们又回到了第三次通话中.我们刚从电话回来main.我们还在if街区内.下一个陈述是printf.变量的值现在为0.所以我们打印一个0.没什么可做的,我们最后返回.
现在我们回到第二个电话.仍为0,所以我们再打印0并返回.
现在我们回到第一个电话.仍为0,所以我们再打印0并返回.
我们打印了3次,所以000
如你所知,在下来的路上,我们不打印.我们在回来的路上打印.到那时,变量是0.然后我们进入if三次的那个块.所以我们递归然后再打印三次.
以递归方式调用函数时,不会消除先前的调用.你把它放在堆栈上.完成后,您将返回到您离开的地方并继续下一个声明.
您可能想要考虑以下三段代码将如何反应:
void recurse() {
static int i = 4;
if (--i) {
recurse();
printf("%d", i);
}
}
Run Code Online (Sandbox Code Playgroud)
第一次调用时打印000.之后什么都不做.
void recurse(int i) {
if (--i) {
recurse(i);
printf("%d", i);
}
}
Run Code Online (Sandbox Code Playgroud)
如果被称为将打印123 recurse(4).作为参数,i每次调用函数时,我们处理的是不同的.
void recurse(int i) {
if (--i) {
printf("%d", i);
recurse(i);
}
}
Run Code Online (Sandbox Code Playgroud)
如果被称为打印321 recurse(4).在下来的路上打印而不是在返回时打印.
void recurse(int i) {
printf("%d", i);
if (--i) {
recurse(i);
}
}
Run Code Online (Sandbox Code Playgroud)
如果被称为打印4321 recurse(4).它打印下来,而不是向上.
void recurse() {
static int i = 4;
printf("%d", i);
if (--i) {
recurse();
}
}
Run Code Online (Sandbox Code Playgroud)
将打印4321.我们正在打印,而不是向上打印.注意参数和static变量如何以这种方式给出相同的结果.但是,如果这是第二次调用,它将不执行任何操作.该参数将再次打印相同的内容.
void recurse() {
int i = 4;
if (--i) {
recurse();
printf("%d", i);
}
}
Run Code Online (Sandbox Code Playgroud)
永远循环.没有static我们i每次都做新的.这将一直运行,直到它重载堆栈并崩溃.没有输出,因为它永远不会成功printf.
检查这个问题的最简单方法是去ideone.com,然后运行代码.询问为什么它打印的东西对于这个网站来说是合理的.但是询问它打印的内容是你应该自己回答的问题.
此代码中存在多个问题:
<stdio.h>不包含,调用printf("%d", i);具有未定义的行为.
main没有参数的原型是int main(void).在某些平台上定义main为void main()不可移植且不正确.始终使用标准原型main并返回有效退出状态以获得良好的风格.
main在C中递归调用函数是一种糟糕的风格,它在C++中具有未定义的行为.
忽略未定义行为意味着任何事情都可能发生的事实,包括印度公司使用可怕的编程测试,程序打印的原因0000是你可能错误地if (i--)测试了测试或者错误地放置了内存中的大括号,或者这个人是完全错误的.该main函数i每次递归调用自身3次递减相同的变量,直到它变为0每个实例打印值i,即0在它返回其调用者之前,包括初始调用main().
static int i = 4;函数内部定义一个i初始值为的全局变量,该变量4只能在定义它的块内访问.所有main访问同一变量的递归实例.
从这个功能的质量和名称中抽象出来.
static在程序启动期间,所有变量仅初始化一次,并保持其值.
当启动例程第一次调用main时,变量的i值为4.然后将其值减小为3并再次调用main.这次的值i是3然后你把它的值减少到2 ......