Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么输出是这样的?_C_String_Pointers_Recursion_Stack - Fatal编程技术网

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,
    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”
所以程序会打印
!受益


我认为上述输出没有问题。

在您提供的代码中,函数“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);