callback function confusion in general - c

I am very confused about callback function. Specifically I am confused about the order of the functions being called in the sequence of functions that make use of callback functions.
For example, I have this piece of code and problem in a question that I recently done, and the solution is below:
The procedure nthPrime shown below computes the nth prime number asynchronously; i.e., it returns
immediately and then calls callback sometime later with the value of the requested prime number. Give
code below that uses this procedure to print the product of the 100th and 200th prime numbers without spinwaiting
or polling (i.e., your code must call this procedure twice and multiply the results). You can use global
variables in your solution if you like.
void nthPrime(int n, void (*callback)(int));
So the solution is:
int t;
void nthPrime(int n, void (*callback)(int));
void foo(int n) {
nthPrime(100, a);
}
void a(int p) {
t = p; // why assign p to t here?
nthPrime(200, b);
}
void b(int p) {
printf("%d\n", t * p); // t*p, but what is p here?
}
However I am totally confused about how the solution (or functions above is being used to implement the request to print the product of the 2 primes).
I guess foo() is being called first. Then I am kind of lost how the sequences is being called (I know some functions return right-away and wait for the result of the "call-back" function to finish???). I am confused what is being returned right away, and what will be run in a near future to return something later in the sequences.

When you call nthPrime(100, a);, nthPrime will calculate the 100th prime, and then call the a function.
When it calls a, p will be that 100th prime.
a then calls nthPrime(200, b);. nthPrime will calculate the 200th prime, then call the b function.
When it calls b, its local variable p will be that 200th prime.
b needs to multiply the prime that it received by the 100th prime that was received by a. It's not possible to access variables in another function's scope directly. That's why a copies its parameter to the global variable t -- this provides the communication between the two callback functions.
In many other languages this would be done with closures rather than global variables, but C doesn't have closures. This limits the flexibility and capability of callbacks in C.

Related

Using static in a recursive function

I came across the following in writing a recursive function:
#include <stdio.h>
void bin_r(unsigned int n)
{
static int s;
s++;
printf("%d", s);
if (n>1)
{
bin_r(n>>1);
}
printf("%d", s);
// ...
}
int main(void) {bin_r(1777);}
12345678910111111111111111111111111
It seems like the 'static'-ness of the variable s works as (I) expected before the recursive function call, but after it it seems to reinitialize it every time. What would be an explanation of what's going on here?
Here's an example of the code if you want to run it: https://onlinegdb.com/znV72a6Gw
You call bin_r again, before the second printf. Meaning, only when the condition (n>1) is true, will the recursion be terminated and the stack can unwind, executing the second printf [however many levels of recursion you have] times without increasing s further.
In your example, you have 11 levels of recursion, which is why you get 11 times "11" printed after the termination condition is met.
The question asks:
It seems like the 'static'-ness of the variable s works as (I)
expected before the recursive function call, but after it it seems to
reinitialize it every time. What would be an explanation of what's
going on here?
As I remarked in comments, I see no evidence of reinitialization. As a static variable declared without an initializer, s is automatically initialized to 0 at the start of the program. At each step down the recursion series, s (of which there is only one, not one per call) is incremented and then printed. The input 1777 is between 210 and 211, so the particular function given recurses to depth 11. That produces
1234567891011
on the way down. On the way back up, s, whose value is then 11, is printed again at each level without further modification, for an additional
1111111111111111111111
In comments you additionally inquired:
And is there a way to keep the static value as it would be before the recursive call (going from 1 to 11) via a static var, or I'd need to use something else for that?
The whole point of a static local variable is that it represents a single object accessed by all executions of the function. That object's lifetime is the same as the whole program's, and, like any object, it retains its last-stored value until a new one is stored or its lifetime ends. So no, there is no way to make it automatically reset after the topmost call of your recursion terminates. Moreover, being declared inside a function, it has no linkage, so it cannot be directly modified from outside the function.
Generally speaking, variables with static storage duration do not play well with recursion. They are incompatible with recursive functions that access them being used in multi-threaded programs, and those declared at block scope, such as your s, are difficult to reset from outside the block in which they are declared.
It would be possible to structure your bin_r() to address the latter issue, maybe like so:
void bin_r(unsigned int n, _Bool top) {
static int s;
s = top ? 1 : (s + 1);
printf("%d", s);
if (n>1) {
bin_r(n>>1, 0);
}
printf("%d", s);
}
Of course, that requires the caller of the top-level execution to pass 1 to signal the function to reset the variable. If you don't like that then you could change that version of bin_r to a helper function, and provide a separate, non-recursive function to perform the top-level call correctly.
But if you're going to do that, then why not just get rid of the static variable while you're at it, maybe something like this:
void bin_r(unsigned int n, int *s) {
(*s)++;
printf("%d", *s);
if (n>1) {
bin_r(n>>1, s);
}
printf("%d", *s);
}
Again, provide a one-arg wrapper for that if you like. Now you're thread-safe, and you have full control.
The other answers/comments are correct here, but here is a basic example to show two different ways that static variables may be used in a basic recursive function: before and after the self-function call:
static int digits -- used/incremented before the recursive function call.
static int sep -- used/incremented after the recursive function call.
void bin_r(unsigned int n)
{
// how many total digits -- this will be finished before unwinding the stack
// here we will increment digits BEFORE the function call, so when the stack
// is unwound we have the full length / number of digits
static int digits, sep;
if (digits==0) printf("%d --> ", n);
digits++;
if (n>1)
bin_r(n>>1, level);
putchar((n&1)==0? '0' : '1'); // == has higher precedence than &
// unwinding the stack -- separate every four digits from RTL, newline at end
// here we will increment sep AFTER the function call, so now that we unwind
// the stack, it will essentially be counting how many frames have been unwound.
sep ++;
if (!((digits-sep)%4) && digits != sep) putchar(' ');
if (digits==sep) {
putchar('\n');
digits = sep = 0; // reset statics
}
}
And here we use both methods to get our output:
1777 --> 110 1111 0001
which is combined together in this line to separate the binary digits every four from right-to-left:
if (!((digits-sep)%4) ...

The definition of a function in C

I have an assignment question which ask me about the definition of a function. I'm not quite sure how it want me to answer. The question is below:
Write the definition of a function multiplier(), which has two real parameters n and m, and which returns value of n multiplied by m
Write the definition of a function multiplier(), which has two real parameters n and m, and which returns value of n multiplied by m
Lets try to unwrap this, there are no real-type in C so Real is the code word for float or double. Function is the name of a subroutine.
The wording of the question is vague definition could ask for the optional prototype declaration(the definition of functions which is usually stored in the header files) which is
float multiplier(float,float);
or the function could be defined and implemented at the same time
float multiplier(float n, float m){
return (n*m);
}
Your question is,
Write the definition of a function multiplier(), which has two real parameters n and m, and which returns value of n multiplied by m
A function is a certain way to write a code, that way you can call it in the main, or wherever, and it performs any tasks assign to it. In your case, for your multiplier, it will perform the function of multiplication. Therefore, it would make sense to use two integers in order to perform this task.
To start, since we will be returning an int, we will call it as that. We set it up like this,
type name (*parameters)
{
}
in your case,
int multiplier(Parameters go here)
For the code:
int multiplier(int m, int n)
{
return m*n;
}
then when we call it in the main, we would pass two numbers for the multiplier and it will return it as a product.
int main()
{
multipler(2, 4); // prints 8
}
I hope this helps, I tried to explain it very basic.

Can this code be called Recursion. If not, which is more advanatgeous, given below code or recursion?

I am having difficulty finding how recursion works. Some text books
says that "Recursion is when a function calls itself again and again
until some base condition is satisfied".
Some books says that "Recursion is when a function calls another
function again and again till some base condition is satisfied".
Which is true? If both are true, can we consider below given example
as a Recursion? If NO, then which is better in terms of performance,
below code or recursion?
def Function1()
{
/* do something */
}
def Function2()
{
for(i=0; i<=10; i++)
{
call Function1()
}
}
As it is, the code shows iterative calls to Function1(), if within the body of Function1() there is a call to Function2(), then it would be an indirect recursion - a function calling second function, which then calls the first again.
In general, a recursive function calls itself, either directly or indirectly. In direct recursion function, foo(), makes another call to itself. In indirect recursion, function foo() makes a call to function moo(), which in turn calls function foo(), until the base case is reached. (and then, the final result is accumulated in the exact reverse order of the initial recursive function call.)
Now, to answer your question:
Can this code be called Recursion. If not, which is more advanatgeous, given below code or recursion?
No. Iteration lacks multiple activation records (or stack frames), which makes it a better alternative.
Recursion should be used according to requirement and when you know the base condition and don't know how many times your loop should be called.
Recursion can be of different types like there can be normal recursion, infinite recursion, indirect recursion etc.
A normal recursion means calling the same function itself until a base condition is satisfied
An infinite recursion is where there will not be any base condition.
An indirect recursion is like when a calls b and b calls c and c calls back a then 'a' is being called indirectly.
Example of basic recursion:
foo()
{
base_condition;
return;
foo();
}
main()
{
foo();
}
Your example base condition can be variable equals runs for 10 times.
fun(int x)
{
if(x == 0)
return;
fun(--x);
}
main
{
fun(10);
}
Please look into the below URL for performance criteria.
performance between looping and recursion
Recursion is when
The control flow passes from a function into the very same function (directly or indirectly) repeatedly without returning first.
In your example, Function1is repeatedly called from Function2, but does return from each call before being called again, so it's not recursively called.
Let me put the pieces together: The code you provided could be recursive or it couldn't. This depends on the fact whether Function1 calls Function2. If this is the case, then you would have a mutual exclusion recursion, as pointed out by EOF.
However, this is a case that does not occur as often as normal recursion (except in pure functional environments). A normal recursion simply consists of a function which calls itself (insteaf of another function).
For further explanations and an introduction how, e. g., the recursive factorial works, see here.
Recursion occurs when a thing is defined in terms of itself or of its
type. Recursion is used in a variety of disciplines ranging from
linguistics to logic. The most common application of recursion is in
mathematics and computer science, where a function being defined is
applied within its own definition. While this apparently defines an
infinite number of instances (function values), it is often done in
such a way that no loop or infinite chain of references can occur.
Source.
So, if you have a foo and in order to calculate or execute foo, you need to recur to foo at least once more, then you have a recursion. Example:
n! = 1 * 2 * 3 * ... * n
This is an iterative definition:
int fact(n) {
int ret = 1;
int i = 1;
while (++i < n) ret *= i;
return ret;
}
This is a recursive definition:
int fact(n) {
return (n == 1) ? 1 : (n * fact(n - 1));
}
Since your code calculates Function2 with multiple usages of Function1, it is not recursive, since you did not need to call Function2 in order to evaluate Function2, nor did you need to call Function1 in order to evaluate Function1. Recursion occurs when something is its own dependency, while your code has a function which depends on another function. Your question about performance is next to impossible to answer, since there are infinite ways to implement a thing with or without recursion, when you compare a recursive approach with a non-recursive approach, then you need to have concrete implementations, or at least very strict ideas of how the two cases would be implemented. However, in general it is a good idea to prefer non-recursive approaches, as recursive approaches often have problems with the stack part of the memory, including stack overflow or infinite function calls and crashes due to bugs.
Recursion is when a function calls itself, either directly or indirectly.
Normally in the C-like languages we use recursion only when the data is tree-like. For example, you have a tree consisting of nodes, with a "next" member to indicate siblings and a "child" member to indicate children (maybe it's an XML file, or a directory tree). You want the the number of nodes so
int getNodes(Node root)
{
int answer = 1;
for(sib = root.next; sib != null; sib = sib.next)
{
answer += 1;
if(sib.child != null)
answer += getNnodes(sib.child);
}
if(node.child != null)
answer += getNodes(node.child);
return answer;
}
You can make the code a bit neater but less efficient by return 0 if root == null.
However you can use recursion for iteration. Think of it as delivering letters to a street. You can go down the street removing letters from your sack (iteration). Or you can deliver letters to the first house in the street, declare the street to be one house shorter, and repeat until the street disappears (recursion). The latter seems eccentric, but it has some advantages for automatic checking of algorithm correctness. If you forget to increment it you can't get stuck in an infinite loop, for example.

difficulty in understanding successive recursive calls

I am trying to understand the following program in which successive recursion function calls are present, but getting confused while tracing how the tack gets loaded.
void func(char*); // function prototype
int main(){
func("123");
return 0;
}
void func(char a[]){
if(a[1]=='\0')
return;
func(a+1);
func(a+1);
printf("%c",a[1]);
}
the output for this is 3 3 2
would appreciate if someone could advise on this one...
does this kind of multiple recursive calls beneficial in any way or find application in specific problem areas..?
Just put yourself in the position of the CPU and step through line-by-line (or use a debugger to help with that task).
The first call is to
func("123")
this call does not satisfy the termination condition a[1] == '\0', so it calls
func("23");
The call to func("23") in turn calls
func("3")
which DOES satisfy the return condition. So, that call returns to the previous caller, func("23").
func("23") proceeds to make another call to func("3") due to the lines
func(a+1);
func(a+1);
Continue this process of executing the program in your mind, and write down what would be in each call to printf. That will explain your output.
UPDATE
Note that the call to printf() happens after the recursive calls, so e.g. a call to
func("123")
would proceed like
Enter func("123")
Termination condition not met
Call func("23")
Call func("23") again
Printf("3") (which is a[1])
Return
Debugging with breakpoints is one way to understand recursion. Another way is to draw the tree of recursive calls.
From the figure, In every level after level0, the printf statement occurs after every two nodes owing to these two lines of code:
func(a+1);
func(a+1);
In general, this becomes a perfect binary tree for any input string of length greater than 0. The total number of nodes is given by this formula:
2^(k+1) - 1 // k is the depth; here k = 2
Total number of printf statements executed can be obtained by this formula:
2^k - 1 // For k=2, there will be 3 printf statements each printing 3,3,2 respectively
the posted code is a rather poorly designed instance of recursion.
The following code has the correct 'tail' form of recursion.
It could be made even better by passing the reversed string back to main and let main print it.
It reverses the order of the string passed to func() by main()
Please, when asking about a runtime problem, post code the compiles, including the necessary #includes for header files so we are not guessing about which headers to include
#include <stdio.h>
void func(char*); // function prototype
int main(){
func("123");
return 0;
}
void func(char a[])
{
if(a[1]=='\0') // check for end of recursive sequence
{
printf( "%c", a[0] ); // last tail action
return;
}
func(a+1); // step+next recursion
printf( "%c", a[0] ); // tail action
return;
}
The recursion can be simply understood as follows.
For example:
Func(int a){
while(a>1)
return a * func(a-1);
}
Suppose a = 5.
What happens is that it returns 5 * func(4).
Now func(4) returns 4 * func(3) and it goes on like this.
Check out this example for use of recursion in fibonacci series.

How does a forward declaration work?

I understand declaring factorial before main. But how can main calculate the answer when the factorial formula comes after it?
#include <stdio.h>
long long factorial(int);
int main()
{
int n;
long long f;
printf("Enter a number and I will return you its factorial:\n");
scanf_s("%d", &n);
if (n < 0)
printf("No negative numbers allowed!\n"); //prevent negative numbers
else
{
f = factorial(n);
printf("The factorial of %d is %ld\n", n, f);
}
return 0;
}
long long factorial(int n)
{
if (n == 0)
return 1;
else
return (n * factorial(n - 1));
}
But how can main calculate the answer when the factorial formula comes after it?
First thing — main does not calculate the answer; it's your factorial function which does it for you. Also there are 3 steps which I feel you need to know about when writing programs:
You write the code in a file.
You compile the file and the compiler checks for syntactical mistakes, no code calculation is happening in this phase its just mere lexical analysis.
Then linking takes place later. If you receive a linker error, it means that your code compiles fine, but that some function or library that is needed cannot be found. This occurs in what we call the linking stage and will prevent an executable from being generated. Many compilers do both the compiling and this linking stage.
Then when you actually run your code — it's then when the code's control flow goes into the factorial function when the calculation happens, i.e. at runtime. Use a Debugger to see this.
The below image is taken from Compiling, Linking and Building C/C++ Applications
From Wiki:
In computer programming, a forward declaration is a declaration of an
identifier (denoting an entity such as a type, a variable, a constant,
or a function) for which the programmer has not yet given a complete
definition....
This is particularly useful for one-pass compilers and separate
compilation. Forward declaration is used in languages that require
declaration before use; it is necessary for mutual recursion in such
languages, as it is impossible to define such functions (or data
structures) without a forward reference in one definition: one of the
functions (respectively, data structures) must be defined first. It is
also useful to allow flexible code organization, for example if one
wishes to place the main body at the top, and called functions below
it.
So basically the main function does not at all need to know how factorial works.
But how can main calculate the answer when the factorial formula comes after it?
The order in which a C program executes is only partially determined by the order in which the text appears.
For instance, look at the printf function you are using. That doesn't appear in your program at all; it is in a library which is linked to your program.
The forward declaration makes it known (from that point in the translation unit) that there is expected to exist such and such a function having a certain name, arguments and return value.
The simple answer is that your C program is processed from beginning to end before it begins to execute. So by the time main is called, the factorial function has already been seen and processed by the C compiler.
An address is assigned to the compiled factorial function, and that address is "backpatched" into the compiled main function when the program is linked.
The reason forward declarations are needed at all is that C is an old-fashioned language originally designed to allow one-pass compilation. This means that the compiler "translates as it goes": functions earlier in a translation unit are compiled and emitted before later functions are seen. To correctly compile a call to a function which appears later (or, generally, appears elsewhere, like in another translation unit), some information must be announced about that function so that it is known at that point.
It works in this manner: let's take an example to find factorial of 3
Recursion :
As factorial of 0 is 1 and factorial of 1 is also 1, so you can write like
if(n <= 1)
return 1;
Since in main function when compiler sees this f = factorial(n); function, the compiler has no idea of what it means. it doesn't know where the function being defined, but it does know the argument the function is receiving is correct, because it's a user defined function that has its definition after main function.
Hence there should be some way to tell the compiler that I am using a function with name factorial which returns long long with a single int argument; therefore you define a prototype of the function before main().
Whenever you call the function factorial the compiler cross checks with the function prototype and ensures correct function call.
A function prototype is not required if you define the function before main.
Example case where function prototyping is not required :
/*function prototyping is not required*/
long long factorial(int n)
{
//body of factorial
}
int main()
{
...
f=factorial(n);
...
}
Here, the compiler knows the definition of factorial; it knows the return type, the argument type, and the function name as well, before it is called in main.

Resources