This is the 22nd article in the C language introductory series.
Most of the programs we have written so far only contain a main function. However, in larger programs, there are usually multiple functions, and the main function contains statements that call other functions.
1 Structure of C Programs
C programs are designed using a procedural programming approach, in contrast to object-oriented programming approaches (such as C++ programs, Java programs, Python programs, etc.).
Procedural programming executes step by step, but what about object-oriented programming?
In object-oriented programming, the focus is not on the steps first, but on the classes available, and the steps are determined within the implementation of those classes.
Therefore, whether it is procedural or object-oriented, there still needs to be a sequence of steps.
The unit of a C program is a function. A C program consists of multiple functions, each completing a specific task. When a certain functionality is needed, the corresponding function is called.
A C program breaks down a large problem into several smaller problems, and each small problem is further divided into even smaller problems, with each small problem implemented by a function.
When writing a program, the main() function addresses the entire problem, calling functions that solve smaller problems, and if necessary, these functions may further call functions that solve even smaller problems, forming a nested function call structure.
This is the structure of a C program, as illustrated below:

Thus, functions are a very important concept in C language.
Let’s look at a program. This program omits many codes because some concepts have not been learned yet. This example is just to illustrate the structure of a C program.
Program 1:

In the main function, six user-defined functions are called. Program 1 only includes the code for the main function and the display_menu function, while the code for the other functions is omitted.
In the switch statement block of Program 1, there is a default statement, which means that when the input is not between 1 and 6, the default action is executed, displaying “Invalid choice, please try again”.
Since the code for the other functions is not provided, when inputs 1-5 are entered, there is no action taken, and the menu simply reappears. When input 6 is entered, the loop exits, and the program ends.
The output of Program 1 is as follows:

2 The Role of Using Pointers as Function Parameters
In Program 1, the function definitions do not have parameters. When a function is defined with parameters, these parameters are called formal parameters, while the arguments passed to the function during the call are called actual parameters. Changes to the formal parameters within the function do not affect the corresponding actual parameters. In other words, if the formal parameter changes, I cannot return the result back to the calling function.
Program 2:

The main function calls function f1 with the actual parameter x, which has a value of 9. In function f1, the value of the formal parameter a is increased by 100, making a’s value 109. However, when the call ends and returns to the main function, is the value of x 9 or 109? The value of x remains 9. Let’s look at the output:

However, if we modify the program so that the formal parameter a is not of int type but of pointer type int *, the actual parameter passed during the call is an address. Let’s look at this program:
Program 3:

In Program 3, the formal parameter a of f1 is of pointer type. When calling f1, the actual parameter must be the address &x, which passes the address of x to a. Then, inside function f1, we see the statement:
*a = *a + 100 ;
*a refers to the value at the address a, which is increased by 100, changing it to 109.
The value at the address a is x, so when function f1 finishes and returns to the main function, the value of x has changed from 9 to 109.
The output of Program 3 is as follows:

The prompt in the second line of this output is actually incorrect; it should say *a=109 instead of a=109. However, the prompt is what we wrote in the printf statement, so it outputs exactly what you wrote.
This example illustrates that when you want to return a result changed inside a function back to the calling function, you can define the function’s formal parameters as pointer types, and the actual parameters during the call should be addresses.
Some may ask: Didn’t you say that changes to formal parameters do not affect actual parameters? How did the actual parameter change now? Note that it is not a that is changing, but *a that is changing. The function does not set a to 109, but sets *a to 109.
In other words, inside the function, through the address a, we find the content at address a, *a, and change the value of *a. Since *a is x, because a is the room number of x (&x), *a is x.
Let’s look at another example:
Program 4:

In Program 4, the function swap is designed to swap the values of two formal parameters. However, when the call ends and returns to the main function, the values of x and y do not swap because the values of formal parameters do not affect actual parameters.
The output of Program 4 is as follows:

However, if we change the parameter types of the swap function to pointer types, and change a to *a and b to *b in the function body, passing the addresses as actual parameters, then when the call ends and returns to the main function, the values of x and y will change.
Program 5:

When calling the swap function, the actual parameters are addresses, which are passed to the formal parameters (pointers). The addresses are not changed by the formal parameters, but the contents at those addresses are changed, so *a and *b change, while a and b remain unchanged.
The output of Program 5 is as follows:

3 Summary
If a function is defined with its formal parameters as pointer type variables, then the actual parameters passed to that function must be addresses. In this case, the results changed inside the function can be saved and returned to the calling function.