About functions in C language

1. The concept of function

In mathematics, we actually have the concept of function, for example: quadratic function y=kx + b, k and b are constants, and given an arbitrary x, we will get a y value. In fact, the concept of function is also introduced in C language, and some translations are: “program”. This translation of “program” is more accurate. A function in C language is a piece of code that completes a specific task. This code has special writing and tuning methods. The C language program is actually composed of a combination of several functions. It can also be said that a single calculation task can be decomposed into several smaller functions (corresponding to larger tasks) to complete. At the same time, if a function can complete a specific task, this function can also be repeated, which improves the efficiency of software development. In the C language we generally see two types of functions:

? Library Functions

? ?Define functions

2. Library functions

2.1 Standard library and headers

The C language standard stipulates various grammatical rules of the C language. The C language does not provide library functions; the international standard of the C language, ANSI C, stipulates the standards for some common functions, which are called standard libraries. Different compiler vendors provide implementations of a series of functions based on the C language standard provided by ANSI. These functions are called library functions. The printf and scanf we learned in the previous content are all library functions, and library functions are also functions. However, these functions are already ready, and we can use them directly as long as we learn them. With library functions, some common functions do not need to be implemented by programmers, which improves efficiency to a certain extent; at the same time, the quality and execution efficiency of library functions are more guaranteed. The standard libraries of various compilers provide a series of library functions. These library functions are declared in different header files according to the division of functions. Header files related to library functions: https://zh.cppreference.com/w/c/header Some are related to mathematics, some are related to strings, some are related to dates, etc. Each header file is included. Related functions, types and other information, don’t be in a hurry when learning library functions. Learn them all at once, learn slowly, and defeat them one by one.

2.2 How to use library functions

There are many tools for learning and viewing library functions, such as: C/C++ official link: https://zh.cppreference.com/w/c/header cplusplus.com: https://legacy.cplusplus. com/reference/clibrary/ Example: sqrt

2.2.1 Function Compute square root Returns the square root of x.

2.2.2 Header file inclusion Library functions are declared in the corresponding header files in the standard library, so the use of library functions must include the corresponding header files. If not included, some problems may occur.

2.2.3 Practice

#include <stdio.h>


#include <math.h>

int main()
{
 double d = 16.0;
 double r = sqrt(d);
 printf("%lf\\
", r);
 return 0;
}

Luck result:

2.2.4 General format of library function files

1. Function prototype

2. Introduction to functions

3. Parameter and return type description

4. Code examples

5. Code output

6. Related knowledge links

3. ?Define functions

After understanding the library functions, our attention should be focused on defining functions. Defining functions is actually more important and can also give programmers more creativity in writing code.

3.1 Grammatical form of function

In fact, the definition function and the library function are the same, and the form is as follows:

? ret_type is the function return type

? fun_name is the function name

? The formal parameters are placed in parentheses

? What is enclosed by {} is the function body

We can think of the function as a circular accelerator, which must input raw materials, and after processing, the product can be produced. The function is also the same, and the function generally inputs these values ( It can be 0 or multiple), and the result is obtained after calculation within the function.

? ret_type is used to represent the type of function calculation result. Sometimes the return type can be void, which means it returns nothing.

? fun_name is for the convenience of using the function; just like the name, when you have a name, you can call it, and when a function has a name, you can call it. Therefore, the function name should be as meaningful as possible according to the function of the function.

The parameters of the function are equivalent to the raw materials sent in the function. The parameters of the function can also be void, which clearly indicates that the function has no parameters. If there are parameters, please clearly explain the type and name of the parameters, as well as the number of parameters.

? The part enclosed by {} is called the function body, and the function body is the process of completing the calculation.

3.2 Examples of functions

For example: Write an addition function to complete the addition operation of two integer variables.

#include <stdio.h>


int main()
{
 int a = 0;
 int b = 0;
 //lose? 
 scanf("%d %d", & amp;a, & amp;b);
 //Adjust the addition function to complete the addition of a and b
 //The result of the summation is placed in r
 //to do

 
 //Output
 printf("%d\\
", r);
 return 0;
}

We name the function according to the function we want to complete: Add. The function Add needs to receive two parameters of integer type, and the result of the function calculation is also an integer. So we write the function based on the above analysis:

#include <stdio.h>

int Add(int x, int y)
{
 int z = 0;
 z = x + y;
 return z;
}

int main()
{
 int a = 0;
 int b = 0;
 //lose? 
 scanf("%d %d", & amp;a, & amp;b);
 //Adjust the addition function to complete the addition of a and b
 //The result of the summation is placed in r
 int r = Add(a, b);
 //Output
 printf("%d\\
", r);
 return 0;
}

The Add function can also be simplified to:

int Add(int x, int y)
{
 return x + y;
}

The parameter part of the function needs to be clearly explained: the number of parameters, the type of each parameter, and the name of the formal parameter. The above is just an example. In the future, we will design functions according to actual needs. The function name, parameters, and return type can all be changed flexibly.

4. Formal parameters and actual parameters

In the process of using a function, the parameters of the function are divided into actual parameters and formal parameters. Let’s look at the code we wrote before:

#include <stdio.h>

int Add(int x, int y)
{
 int z = 0;
 z = x + y;
 return z;
}

int main()
{
 int a = 0;
 int b = 0;
 //lose? 
 scanf("%d %d", & amp;a, & amp;b);
 //Adjust the addition function to complete the addition of a and b
 //The result of the summation is placed in r
 int r = Add(a, b);
 //Output
 printf("%d\\
", r);
 return 0;
}

4.1 Actual parameters

In the above code, the 2nd to 7th chapters are the definition of the Add function. After the function is established, the Add function is called in the 17th chapter. When we call the Add function in Chapter 17, the parameters a and b passed to the function are called actual parameters, or actual parameters for short. The actual parameters are the parameters actually passed to the function.

4.2 Formal parameters

In the above code, when defining the function in the second step, the x and y written in parentheses after the function name Add are called formal parameters, or formal parameters for short. Why are they called formal parameters? In fact, if you just define the Add function and do not adjust it, the parameter x of the Add function

and y only exist formally and will not apply for memory space and will not actually exist, so they are called formal parameters. Formal parameters only apply for space in memory in order to store the values passed by actual parameters when the function is called. This process is the instantiation of the form.

4.3 Relationship between actual parameters and formal parameters

Although we mentioned that actual parameters are passed to formal parameters and they are related, formal parameters and actual parameters are separate memory spaces. This phenomenon can be observed through debugging. Please take a look at the code and debugging demonstration below:

#include <stdio.h>

int Add(int x, int y)
{
 int z = 0;
 z = x + y;
 return z;
}

int main()
{
 int a = 0;
 int b = 0;
 //lose? 
 scanf("%d %d", & amp;a, & amp;b);
 //Adjust the addition function to complete the addition of a and b
 //The result of the summation is placed in r
 int r = Add(a, b);
 //Output
 printf("%d\\
", r);
 return 0;
}

We can observe during debugging that x and y did get the values of a and b, but the addresses of x and y are different from the addresses of a and b, so we can understand that the formal parameters are actual parameters? Temporary copy?

5. return statement

In the design of functions, return statements often appear in functions. Here are some precautions for using return statements.

? Return can be followed by a numerical value or an expression. If it is an expression, the expression will be executed first, and then the result of the expression will be returned.

? There can be nothing after return, just write return; This writing method is suitable for situations where the function return type is void.

? The value returned by return is inconsistent with the function return type, and the system will automatically implicitly convert the returned value to the function’s return type.

After the return statement is executed, the function returns completely and the subsequent code is no longer executed.

? If there is an if statement equal to ? in the function, make sure there is return in each case, otherwise a compilation error will occur.

6. Array as function parameter

When using a function to solve a problem, it is inevitable that the array will be passed to the function as a parameter and the array will be operated inside the function. For example: write two functions to set all the contents of an integer array to -1, and then write two functions to print the contents of the array. Thinking simply, the basic form should be like this:

#include <stdio.h>

int main()
{
 int arr[] = {1,2,3,4,5,6,7,8,9,10};
 set_arr();//Set the array content to -1
 print_arr();//Print the contents of the array
 return 0;
}

In order for this set_arr function to be able to set the contents of the array, it must pass the array as a parameter to the function. At the same time, when setting each element of the array, the function must also traverse the array and need to know the number of elements in the array. So we need to pass 2 parameters to set_arr, one is the array, and the other is the number of elements in the array. A careful analysis of print_arr is also the same. Only by getting the array and the number of elements can we traverse and print each element of the array.

#include <stdio.h>

int main()
{
 int arr[] = {1,2,3,4,5,6,7,8,9,10};
 int sz = sizeof(arr)/sizeof(arr[0]);
 set_arr(arr, sz);//Set the array content to -1
 print_arr(arr, sz);//Print the contents of the array
 return 0;
}

The array is passed as a parameter to the set_arr and print_arr functions, so how should these two functions be designed? Here we need to know the key knowledge about array parameter passing:

? The formal parameters of the function must match the number of actual parameters of the function.

? The actual parameters of the function are arrays, and the formal parameters can also be written in array form.

? If the formal parameter is a ?-dimensional array, the array can be omitted.

? If the formal parameter is a ?-dimensional array, ? can be omitted, but the column cannot be omitted.

? When passing parameters in an array, formal parameters will not create a new array.

? The array of formal parameter operation and the array of actual parameters are the same array. Based on the above information, we can implement these two functions:

void set_arr(int arr[], int sz)
{
 int i = 0;
 for(i=0; i<sz; i + + )
 {
 arr[i] = -1;
 }
}

void print_arr(int arr[], int sz)
{
 int i = 0;
 for(i=0; i<sz; i + + )
 {
 printf("%d ", arr[i]);
 }
 printf("\\
");
}

7. Nested reconciliation and chained access

7.1 Nested adjustment?

Nested tuning is the mutual tuning between functions. Each function is a piece of music. It is precisely because of the seamless cooperation of multiple music parts that we can build exquisite music toys. Because the functions effectively coordinate with each other, a relatively small program was finally written. Suppose we calculate how many days there are in a certain year? , if you want function implementation, you can design 2 functions:

? is_leap_year(): Determine whether it is a leap year based on the year

? get_days_of_month(): Adjust ?is_leap_year to determine whether it is a leap year, and then calculate the number of days based on ?

int is_leap_year(int y)
{
 if(((y%4==0) & amp; & amp;(y 0!=0))||(y@0==0))
 return 1;
 else

 return 0;
}

int get_days_of_month(int y, int m)
{
 int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 int day = days[m];
 if (is_leap_year(y) & amp; & amp; m == 2)
 day + = 1;
 
 return day;
}


int main()
{
 int y = 0;
 int m = 0;
 scanf("%d %d", & amp;y, & amp;m);
 int d = get_days_of_month(y, m);
 printf("%d\\
", d);
 return 0;
}

This piece of code completes a unique function. There are a lot of function calls reflected in the code:

? The main function calls scanf, printf, get_days_of_month

? The get_days_of_month function calls ? is_leap_year

Some of the future code will be nested adjustments between functions, but functions cannot be nested.

7.2 Chain access

The so-called chain access is to use the return value of one function as the parameter of another function. Stringing the functions together like a chain is the chain access of the function. ?like:

#include <stdio.h>

int main()
{
 int len = strlen("abcdef");//1.strlen finds the length of a string
 printf("%d\\
", len); //2. Print?
 return 0;
}

The code above has written two statements to complete the action. What if the return value of strlen is directly used as the parameter of the printf function? This is an example of chained access.

#include <stdio.h>

int main()
{
 printf("%d\\
", strlen("abcdef"));//chain access
 return 0;
}

8. Declaration and definition of functions

8.1 Individual items

Generally, when we use a function, we write the function directly and use it. For example: We need to write a function to determine whether the year is a leap year.

#include <stido.h>

//Judge? Is the year a leap year?

int is_leap_year(int y)
{
 if(((y%4==0) & amp; & amp;(y 0!=0)) || (y@0==0))
 return 1;
 else

 return 0;
}

int main()
{
 int y = 0;
 scanf("%d", & amp;y);
 int r = is_leap_year(y);
 if(r==1)
 printf("Leap year\\
");
 else

 printf("?Leap year\\
");
 return 0;
}

Then if we put the definition of the function after the call of the function, as follows:

#include <stido.h>

int main()
{
 int y = 0;
 scanf("%d", & amp;y);
 int r = is_leap_year(y);
 if(r==1)
 printf("Leap year\\
");
 else

 printf("?Leap year\\
");
 return 0;
}

//Judge? Is the year a leap year?

int is_leap_year(int y)

{
 if(((y%4==0) & amp; & amp;(y 0!=0)) || (y@0==0))
 return 1;
 else

 return 0;
}

When this code is compiled on VS2022, the following warning message will appear:

This is because when the C language compiler compiles the source code, it scans from the first line downwards. When it encounters the is_leap_year function call on the seventh line, it does not find the definition of is_leap_year in the previous line. The above warning was reported. How to solve this problem? That is, declare the function is_leap_year before calling the function. When declaring the function, you only need to explain clearly: the function name, the return type of the function and the parameters of the function. For example: int_is_leap_year(int y); this is a function declaration. In the function declaration, only the parameter type is retained, and the name can be omitted. The code will compile normally if it becomes like this.

#include <stido.h>

int is_leap_year(int y); //Function declaration

int main()
{
 int y = 0;
 scanf("%d", & amp;y);
 int r = is_leap_year(y);
 if(r==1)
 printf("Leap year\\
");
 else

 printf("?Leap year\\
");
 return 0;
}

//Judge? Is the year a leap year?

int is_leap_year(int y)

{
 if(((y%4==0) & amp; & amp;(y 0!=0)) || (y@0==0))
 return 1;
 else

 return 0;
}

Function debugging must be satisfactory, declare it first and then use it; the definition of a function is also a special declaration, so it is okay if the function definition is placed before debugging.

8.2 Multiple files

Generally, when we write code in an enterprise, there may be a lot of code, and we will not put all the code in one file; we often split the code into multiple files based on the function of the program. . Under normal circumstances, the function declaration and type declaration are placed in the header file (.h), and the implementation of the function is placed in the source file (.c) file. as follows:

add.c

//Definition of function

int Add(int x, int y)
{
 return x + y;
}

add.h

//Declaration of function

int Add(int x, int y);

test.h

#include <stdio.h>

#include "add.h"

int main()
{
 int a = 10;
 int b = 20;

 //Function call?
 int c = Add(a, b);
 printf("%d\\
", c);
 return 0;
}

operation result:

With the understanding of function declaration and function definition, it will be more convenient for us to write code.

8.3 static and extern

static and extern are both keywords in C language.

static means static, it can be:

? Modify local variables

? Modify global variables

?Modify function

extern is used to declare external symbols. Before explaining static and extern, let’s talk about: operating scope and life cycle.

Scope is a programming concept. Generally speaking, the name found in a segment of program code is not always valid (available). The code range that limits the validity of the name is the name. The scope of work.

1. The scope of a local variable is the local scope where the variable is located.

2. The scope of global variables is the entire process (project). The life cycle refers to the time period between the creation of a variable (application for memory) and the destruction of the variable (reclaiming memory).

1. The life cycle of local variables is: when the operation domain variable is created, the life cycle begins, and the operation domain life cycle ends.

2. The life cycle of global variables is: the life cycle of the entire program.

8.3.1 static modified local variables:

//Code 1

#include <stdio.h>

void test()
{
 int i = 0;
 i + + ;
 printf("%d ", i);
}

int main()
{
 int i = 0;
 for(i=0; i<5; i + + )
 {
 test();
 }
 return 0;
}
/Code 2

#include <stdio.h>

void test()
{
 //static modifies local variables
 static int i = 0;
 i + + ;
 printf("%d ", i);
}

int main()
{
 int i = 0;
 for(i=0; i<5; i + + )
 {
 test();
 }
 return 0;
}

Regarding the effects of code 1 and code 2, understand the meaning of static modified local variables. The local variable i in the test function in code 1 is created every time the test function is entered (the life cycle begins) and assigned a value of 0, then + +, and then printed. When the function is exited, the variable life cycle will end (released) Memory). In code 2, we can see from the output results that the value of i has a cumulative effect. In fact, after i in the test function is created, it will not be destroyed when exiting the function. If you re-enter the function, the variable will not be re-created. , continue calculation directly from the last accumulated value. Conclusion: static modification of local variables changes the life cycle of the variable. The essence of the life cycle change is to change the storage type of the variable. Originally, a local variable was stored in the stack area of the memory, but after being modified by static, it was stored in static district. Variables stored in the static area are the same as global variables. The life cycle is the same as the life cycle of the program. Only when the program ends, the variables are destroyed and the memory is recycled. But the scope remains unchanged.

Usage suggestion: After these variables exit the function in the future, if we still want to retain the value, we can use static modification when entering the function next time to continue using it.