C 为什么输出是这样的?
我必须分析这段代码,我真的不明白它是如何打印出超过“!”的内容的C 为什么输出是这样的?,c,string,pointers,recursion,stack,C,String,Pointers,Recursion,Stack,我必须分析这段代码,我真的不明白它是如何打印出超过“!”的内容的 #包括 int f(int i,int*v,char*p){ int x; 如果(strlen(p)>0){ x=f(++i,v,++p); printf(“%c”,*(-p)-*(v+(-i)); }否则 printf(“!”); 返回x; } int main(){ int v[4]={3,1,2,4},a=3124; 字符k[5]=“HOGF”; char*p=k; a=f(0,v,p); 返回0; } 预期产量为 !!贝
#包括
int f(int i,int*v,char*p){
int x;
如果(strlen(p)>0){
x=f(++i,v,++p);
printf(“%c”,*(-p)-*(v+(-i));
}否则
printf(“!”);
返回x;
}
int main(){
int v[4]={3,1,2,4},a=3124;
字符k[5]=“HOGF”;
char*p=k;
a=f(0,v,p);
返回0;
}
预期产量为
!!贝尼
为什么函数不停在“!”?f返回的值未定义,因为它是未初始化变量x的“值”,但该值从未“真正”使用过
为什么函数不停在“!”
因为代码在字符串“HOGF”中前进,直到到达结尾的空字符,在这种情况下,strlen
是0,显然不是>0
所以“!”是print,所以递归调用被“popped”生成其他字符的print
详细内容:
- 在第一次从main执行f时,变量p指向“HOGF”,i值为0,字符串不是空的,因此递归调用
- 2次p指向“OGF”,i值为1,字符串不为空,因此递归调用
- p的3倍指向“GF”,i的值为2,字符串不是空的,所以递归调用
- p的4倍指向“F”,i的值为3,字符串不是空的,所以递归调用
- 5次p指向“”,i值为4,
为假,因此“!”为打印strlen(p)>0
- 回到f的4执行,两个
取消p和i的递归调用参数中的--
,因此p指向f和i值3,++
为4,以便打印字符“f'-4”为“B”v[3]
- 回到f的3次执行,两个
取消p和i的递归调用参数中的--
,因此p指向G和i值2,++
为2,以便打印字符“G'-2”为“E”v[2]
- 回到f的2执行,两个
取消p和i的递归调用参数中的--
,因此p指向O和i值1,++
为1,以便打印字符“O'-1”为“N”v[1]
- 回到f的第一次执行,两个
取消p和i的递归调用参数中的--
,因此p指向H和i值0,++
为3,以便打印字符“H'-3”为“E”v[0]
!受益
我认为上述输出没有问题。
在您提供的代码中,函数“f”被递归调用,这意味着您正在调用函数本身。 当执行语句'a=f(0,v,p)`时,执行上下文从主函数切换到f函数。
(strlen(p)>0)
此时满足此条件,因为p表示“HOGF”,且其长度大于0。因此,执行if块而不是else块现在在if块中,
x=f(++i,v,++p)
被执行,这就是递归函数调用。当您仍在函数f的上下文中时,可以再次调用它。这会将一个新的执行上下文添加到调用堆栈中,并且由于传递的是++p,而不是“HOGF”,当指针递增到下一个地址时,传递的是“OGF”。
在遇到a return语句之前,将发生此堆栈添加操作。
也就是说,5个不同的函数堆叠在主函数的顶部。下面的函数不能继续执行,除非上面的函数返回并弹出。
在本例中,“OGF”->“GF”->“F”->”是传递给函数的值,以便最顶端的函数接收一个空字符串作为其参数
此时,当一个空字符串作为参数传递给f函数时,
(strlen(p)>0)
将计算为false,并且将第一次执行else块。因此,将“!”打印为输出中的第一项。你会问为什么执行不会在这里停止。
因为我们已经构建了一个函数f的堆栈,在打印“!”之后,函数直到返回时才结束。当遇到return语句时。这将弹出堆栈中最顶层的f函数,并返回最顶层f函数中的“x”值。
“x”的值将是垃圾值,因为x是未初始化的变量。
意味着来自最顶层f函数的x值将作为值传递给执行堆栈中正下方f函数中的x。在此上下文中,函数仍有
printf(“%c”)、*(-p)-*(v+-i))
和要执行的返回语句。*(-p)-*(v+(-i))
负责从“HOGF”中的字符中减去并打印“BENE”,而不是
例如,--p
返回指向“F”的指针,--i
将i减至3,因此“F'-v[3]变为“F'-4”,即“B”
打印“B”后,函数将“x”的值返回给执行堆栈中的下一个函数。类似地,“E”、“N”、“E”也会被打印出来,最后函数会将“x”的值返回到最初调用函数“f”的主函数。
有趣的是,“x”的值虽然不总是0,但在f函数的每个上下文中都是相同的,它将等于负责打印“!”的最顶层f函数传递的值。您可以通过观察和更好地理解递归来理解这一点。
需要考虑的资源:
递归和调用堆栈:
*(v+(-i))如何变成v[-i]:
如果这还不能消除您的疑虑,请随时发表评论。您是否在调试器中执行了该代码,以便逐步执行?您好,是的。我确实运行了代码,并决定在if条件下和在else之后打印x。我得到的是一堆预期的地址。除此之外,我可以
(strlen(p)>0)
x=f(++i,v,++p);