You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言递归schema函数调用plus函数的运行原理解析

问题背景

我尝试使用在线调试器分析一段C语言代码的运行逻辑,但始终无法理清其执行流程。
使用的在线C编译器为OnlineGDB提供的在线C编译环境。

待分析代码
#include <stdio.h>

unsigned int plus(unsigned int x, unsigned int y){
  return x+y;
}

unsigned int schema (unsigned int x, unsigned int y, unsigned int a, unsigned int (*f)(unsigned int, unsigned int)){
    return((y==0)?a:(*f)(schema(x,y-1,a,f),x));
}

unsigned int prod(unsigned int x, unsigned int y){
    return(schema(x,y,0,plus));
}

int main()
{
    int m,n;
    
    printf("Donner deux nombres ? : ");
    scanf("%d %d", &m, &n);
    printf("%d * %d = %d\n", m, n, prod(m,n));

    return 0;
}
核心疑问

schema 函数是如何传入正确参数调用 plus 函数,最终实现乘法计算的?
对应代码可在OnlineGDB平台在线运行调试。

调试记录

输入3和2时的GDB调试过程记录如下:

Reading symbols from a.out...
(gdb) run
Starting program: /home/a.out 
Donner deux nombres ? : 3 2

Breakpoint 2, prod (x=21845, y=1431655088) at main.c:20
20      unsigned int prod(unsigned int x, unsigned int y){
(gdb) step

Breakpoint 1, prod (x=3, y=2) at main.c:21
21          return(schema(x,y,0,plus));
(gdb) step

Breakpoint 4, schema (x=32767, y=4294962119, a=0, f=0xf0b5ff) at main.c:16
16      unsigned int schema (unsigned int x, unsigned int y, unsigned int a, unsigned int (*f)(unsigned int, unsigned int)){
(gdb) step

Breakpoint 3, schema (x=3, y=2, a=0, f=0x555555555189 <plus>) at main.c:17
17          return((y==0)?a:(*f)(schema(x,y-1,a,f),x));
(gdb) step

Breakpoint 4, schema (x=0, y=0, a=0, f=0x0) at main.c:16
16      unsigned int schema (unsigned int x, unsigned int y, unsigned int a, unsigned int (*f)(unsigned int, unsigned int)){
(gdb) step

Breakpoint 3, schema (x=3, y=1, a=0, f=0x555555555189 <plus>) at main.c:17
17          return((y==0)?a:(*f)(schema(x,y-1,a,f),x));
(gdb) step

Breakpoint 4, schema (x=0, y=24, a=0, f=0x0) at main.c:16
16      unsigned int schema (unsigned int x, unsigned int y, unsigned int a, unsigned int (*f)(unsigned int, unsigned int)){
(gdb) step

Breakpoint 3, schema (x=3, y=0, a=0, f=0x555555555189 <plus>) at main.c:17
17          return((y==0)?a:(*f)(schema(x,y-1,a,f),x));
(gdb) step
18      }
(gdb) step

Breakpoint 6, plus (x=3, y=0) at main.c:12
12      unsigned int plus(unsigned int x, unsigned int y){
(gdb) step

Breakpoint 5, plus (x=0, y=3) at main.c:13
13          return x+y;
(gdb) step
14      }
(gdb) step
schema (x=3, y=1, a=0, f=0x555555555189 <plus>) at main.c:18
18      }
(gdb) step

Breakpoint 6, plus (x=3, y=1) at main.c:12
12      unsigned int plus(unsigned int x, unsigned int y){
(gdb) step

Breakpoint 5, plus (x=3, y=3) at main.c:13
13          return x+y;
(gdb) step
14      }
(gdb) step
schema (x=3, y=2, a=0, f=0x555555555189 <plus>) at main.c:18
18      }
(gdb) step
prod (x=3, y=2) at main.c:22
22      }
(gdb) step
__printf (format=0x555555556023 "%d * %d = %d\n") at printf.c:28
28      printf.c: No such file or directory.
(gdb) continue
Continuing.
3 * 2 = 6
[Inferior 1 (process 2233) exited normally]
(gdb) 
运行逻辑说明

这段代码靠递归累加实现乘法,各部分作用和执行流程如下:

  • schema是通用递归工具函数,第四个参数是函数指针,用来指定每一步递归要执行的运算,第三个参数a是累计计算的初始值,乘法场景下初始传0。
  • 递归终止条件是计数参数y减到0,此时直接返回存好的累计结果a。
  • 未触发终止条件时,会先递归调用自身将y减1,拿到上一层的计算结果,再把这个结果和固定值x传给传入的运算函数f,计算得到的值就是当前层的返回值。
  • prod函数调用schema时,传入的运算函数是plus(即加法运算),逻辑等价于把x重复累加y次,最终结果自然就是x与y的乘积。

以输入3和2为例,完整调用顺序和调试记录完全对应:

  1. 最外层调用schema(3,2,0,plus),此时y=2不等于0,需要先计算schema(3,1,0,plus)的返回值,再将返回值和3传入plus做加法
  2. 进入schema(3,1,0,plus),y=1也不等于0,需要先计算schema(3,0,0,plus)的返回值,再将结果和3传入plus
  3. 进入schema(3,0,0,plus),y=0触发终止条件,直接返回初始值0
  4. 回到第二层schema调用,执行plus(0,3)得到3,作为schema(3,1,0,plus)的返回值
  5. 回到最外层schema调用,执行plus(3,3)得到6,也就是3*2的最终计算结果

调试过程中看到的参数异常栈帧(比如x=32767、f为空指针这类),是GDB还未单步进入对应函数、栈帧未初始化完成时读到的内存脏值,无需在意,单步进入函数后参数值就会恢复正常。


内容的提问来源于stack exchange,提问作者Maykiwo GNO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 11:48:26