I'm using online debugger to try to understand, how it works but it is not clear.
https://www.onlinegdb.com/online_c_compiler
The code:
#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;
}
How does the schema function to calls plus function with the correct parameters ?
The code is here : https://onlinegdb.com/nAglj8NwZr
Here the debug :
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)
Thanks a lot if someboby could explain this code.
CodePudding user response:
Consider providing 4
and 5
to your program. Perhaps this will help you to visualize the recursion.
prod(4, 5)
schema(4, 5, 0, plus)
plus(schema(4, 5-1, 0, plus), 4)
plus(plus(schema(4, 4-1, 0, plus), 4), 4)
plus(plus(plus(schema(4, 3-1, 0, plus), 4), 4), 4)
plus(plus(plus(plus(schema(4, 2-1, 0, plus), 4), 4), 4), 4)
plus(plus(plus(plus(plus(schema(4, 1-1, 0, plus), 4), 4), 4), 4), 4)
plus(plus(plus(plus(plus(0, 4), 4), 4), 4), 4)
plus(plus(plus(plus(4, 4), 4), 4), 4)
plus(plus(plus(8, 4), 4), 4)
plus(plus(12, 4), 4)
plus(16, 4)
20
Note that because prod
only calls another function, tail-call optimization may take place. However, schema
calls itself, and then feed the result to the function pointer provided, so those stack frames have to remain, meaning TCO cannot be performed.
If, however, you were dealing with a sightly smarter schema
function, which used that a
parameter usefully as an updating accumulator, TCO would be possible.
unsigned int schema(unsigned int x, unsigned int y, unsigned int a,
unsigned int (*f)(unsigned int, unsigned int)) {
if (y == 0) return a;
return schema(x, y-1, f(x, a), f);
}