为什么这样的输出?

时间:2020-07-02 16:50:44

标签: c string pointers recursion stack

我必须分析这段代码,而且我真的不明白它是如何打印出比“!”更多的内容的。

#include <stdio.h>

int f(int i, int *v, char* p){
    int x;
    if(strlen(p)>0){
        x=f(++i,v,++p);
        printf("%c", *(--p)-*(v+(--i)));
    }else
    printf("! ");
    return x;
}

int main(){
    int v[4]={3,1,2,4}, a=3124;
    char k[5]="HOGF";
    char *p=k;
    a=f(0,v,p);
    return 0;
    
}

预期输出是

!贝恩

为什么函数不停止在“!”?

2 个答案:

答案 0 :(得分:1)

f 返回的值是不确定的,因为它是未初始化变量 x 的“值”,但从未真正使用过该值。

Why doesn't the function stop at " ! "

因为代码在字符串“ HOGF”中进行处理直至到达结尾的空字符,并且在这种情况下,strlen为0(显然不是>0,所以打印了“!”,则递归)呼叫被“弹出”以产生其他字符的印记。

详细信息:

  • main 第一次执行 f 时,变量 p 指向“ HOGF”和 i 值0,字符串不为空,所以递归调用
  • p 的2次指向“ OGF”和 i 的值为1,字符串不为空,因此递归调用
  • 3次 p 指向“ GF”和 i 值2,字符串不为空,因此递归调用
  • 4次 p 指向“ F”且 i 的值为3,字符串不为空,因此递归调用
  • 5次 p 指向“”,并且 i 值4,strlen(p)>0为假,因此打印“!”
  • 返回到 f 的4次执行,两个--取消 p 的递归调用参数中的++ i ,因此 p 指向F,而 i 的值3,v[3]为4,因此打印字符'F'-4为'B '
  • 返回到 f 的3次执行,两个--取消 p 的递归调用参数中的++ i ,因此 p 指向G,而 i 值2,v[2]为2,因此打印字符'G'-2为'E '
  • 返回到 f 的2次执行,两个--取消 p 的递归调用参数中的++ i ,因此 p 指向O,而 i 值1,v[1]为1,因此打印字符'O'-1为'N '
  • 返回到 f 的第一次执行,两个--取消 p 的递归调用参数中的++ i ,因此 p 指向H,而 i 的值为0,v[0]为3,因此打印字符'H'-3为'E '

因此程序将打印! BENE

答案 1 :(得分: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”被传递。

在遇到return语句之前,将一直添加到堆栈中。
也就是说,在主要功能之上叠加了5种不同的功能。除非上面的函数返回并弹出,否则下面的函数无法继续执行。
在这种情况下,“ OGF”->“ GF”->“ F”->“”是传递给函数的值,以便最顶层的函数接收一个空字符串作为其参数
此时,当将空字符串作为参数传递给f函数时,(strlen(p)>0)的值将为false,并且else块将首次执行。因此,在输出中首先打印“!” 。
您问为什么执行不会在这里停止。

因为我们已经建立了函数f的堆栈,并且在打印“!”之后函数才结束,直到返回为止。遇到return语句时。这将弹出堆栈中最上面的f函数,并返回最上面的f函数的'x'值。
x的值将是垃圾值,因为x是未初始化的变量

x=f(++i,v,++p);

表示来自最顶部f函数的x的值将作为值传递给执行栈中位于其下方的f函数中的x。在这种情况下,该函数仍然具有printf("%c", *(--p)-*(v+(--i)))和要执行的return语句。
*(--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函数传递的值。您可以通过更好地观察和理解递归来理解这一点。

要考虑的资源:

递归和调用堆栈:https://www.freecodecamp.org/news/how-recursion-works-explained-with-flowcharts-and-a-video-de61f40cb7f9/

*(v +(-i))如何变成v [-i]:https://www.prismnet.com/~mcmahon/Notes/arrays_and_pointers.html

如果仍不能清除您的疑问,请随时发表评论。

相关问题