[C language] from introduction to penetration (function)

preface:
This article explains to you how to master the basic use and recursion of functions.

C language function is a function used to compile c language, generally including character library function, mathematical function, directory function, process function, diagnosis function, operation function, etc. "Function" is translated from English function. In fact, function means "function" and "function" in English. In essence, functions are used to complete certain functions.

1. What is the function

We often see the concept of function in mathematics. But do you know the functions in C language? In C language, function is very important. In the process of writing code, it is inseparable from function. Contains the main function we wrote, which is also a function.

Wikipedia concept of function:

1. In computer science, a subroutine is a part of code in a large program, which is composed of one or more statement blocks. It is responsible for completing a specific task and has relative independence compared with other codes.

2. Generally, there are input parameters and return values, which provide encapsulation of the process and hiding of details. These codes are usually integrated into software libraries.

Function provides the encapsulation of the process and the hiding of details, which can make our code more concise. For example, printf and scanf are input-output functions. We don't need to pay attention to what their underlying code looks like. We just need to use it. Using functions can reduce redundant code and standardize code.

The function classification in C language can be simply divided into

  1. Library function
  2. Custom function

2. Library function

Why library functions?

Let's take an example first. We know that in the process of learning c language, we can't wait to write the code every time. If we want to know whether the result is correct, we have to print it for confirmation. Then we need to use the library function printf to print; When we need to calculate the k power of n, the keyboard does not have the symbol of power, so we can use the library function pow to calculate the power.

Therefore, we often need to use the basic functions. They are not business code, but may be used by every programmer in the development process. In order to support portability and improve efficiency, a compiler is used to provide a series of library functions to facilitate programmers' software development.

But note:

C language specifies some library functions, such as function name, parameter standard, return value type, function function, etc., but the library function itself does not provide library functions, which are provided by compiler manufacturers, such as VS, gcc and other compilers. Moreover, in different compilers, the details of the same library function may be different, but the functions are the same.

So how can we learn such rich library functions?

Here is a link with rich explanations and descriptions of library functions:
Click here!!! cplusplus.com

How to learn library functions:

  1. See the explanation of the library function
  2. Look at the use of examples
  3. Used in the compiler

We can try to learn a library function: strcpy

First, go to the link and search the strcpy library function:

Then we can see some contents about strcpy, including its name, function and detailed explanation. Copy the string of source to destination:

At this time, some people think wow, I can't speak English, but many times page translation and some translation software are very convenient. We can understand them through their translation, so that we can make progress.

Then, what you see next is the contents of its formal parameters, which are overwritten. There is also his return type. Here, it means that he returns the starting address of the destination space:

Finally, you can see his example, create several character arrays, initialize the array, call strcpy() function to copy the contents of str1 to str2, or copy the contents of "" directly input into str3. Also note that string.h is quoted in the header file here:

Then, except for examples, where can I see the header file I need to quote? Don't worry, there are also some next to the plate:

Then we can try this function ourselves:

#include <string.h>
int main()
{
	char arr1[] = "heoooooo!";
	char arr2[20];

	strcpy(arr2, arr1);
	printf("%s\n", arr1);
	printf("%s\n", arr2);
	return 0;
}

Then we just said that the return value of the strcpy library function is the target space, that is, the starting address of the copied space, so can we also print the result after receiving the return value?

#include <string.h>
int main()
{
	char arr1[] = "heoooooo!";
	char arr2[20];

	char* ret = strcpy(arr2, arr1);
	printf("%s\n", arr1);
	printf("%s\n", arr2);
	printf("%s\n", ret);
	return 0;
}

The answer is yes, so we can slowly understand and use library functions.

The common library functions are:

A secret that library functions must know is that when using library functions, they must include #include the corresponding header file. Learn the above library functions by referring to the documents, and you can master the usage of library functions.

3. User defined functions

So there are so many library functions. Why do you need custom functions! If library functions can do all kinds of things, what do programmers need? So custom functions are also important.

Like library functions, custom functions have function names, return value types, and function parameters. But the difference is that these are designed by ourselves. This gives programmers a lot of room to play.

Structure of custom function:

ret_type fun_name(para1, * )
{
 statement;//Statement item
}
//ret_type return type
//fun_name function name
//Param1 function parameters

Let's take chestnuts for example, which is easy to understand:

//Calculate the sum of two numbers

int jia(int a, int b)//Create function
//Return type int function name jia (function parameter creation int a,int b)
{
	int sum = 0;
	sum = a + b;//Statement block
	return sum;
}

int main()
{
	int a = 20;
	int b = 10;
	int sum = jia(a, b);//Call function, pass in parameters
	printf("%d", sum);
	return 0;
}

In fact, a custom function is that we write a function and encapsulate it in a function. When we need to use it, we can call it. This greatly simplifies the contents of the main function, and packages the well functioning code to make the code cleaner.

Let's take another look at this function:

//Writing a function can exchange the contents of two integer variables.
#include <stdio.h>
void Swap1(int x, int y)//Create function
{
 int tmp = 0;
 tmp = x;//Statement block
 x = y;
 y = tmp;
}

int main()
{
 int num1 = 1;
 int num2 = 2;
 printf("Before exchange:num1 = %d num2 = %d\n ",num1,num2);
 Swap1(num1, num2);//call
 printf("After exchange:num1 = %d num2 = %d\n", num1, num2);
 return 0;
 }

Is this function feasible? Many people think that functions also exchange two numbers, but there is no exchange of two numbers here. We can see the results.

Why is there no change? Because what we passed here is only a value, not the address of num1 and num2, so the change of that value will not change the number stored in the address of num1 and num2, nor return the value back to num1 and num2. Let's take another look at this function:

void Swap2(int* px, int* py)
{
	int tmp = 0;
	tmp = *px;
	*px = *py;
	*py = tmp;
}
int main()
{
 int num1 = 1;
 int num2 = 2;
 printf("Before exchange:num1 = %d num2 = %d\n",num1,num2);
 Swap2(&num1, &num2);//call
 printf("After exchange:num1 = %d num2 = %d\n", num1, num2);
 return 0;
 }

In this code, we can see that the values of num1 and num2 are exchanged, but the difference is whether we pass the value or address when passing the parameter. In the second function, we pass the addresses of num1 and num2, and what changes in the function will also be the value on the address.

4. Function parameters

The function parameters passed in when creating the function and the parameters passed in the calling function are actually the actual parameters and formal parameters of our function:

Actual parameters:
The parameters that are really passed to the function are called arguments. Arguments can be constants, variables, expressions, functions, etc. No matter what type of arguments are, they must have definite values when making a function call in order to pass these values to the formal parameters.

Formal parameter (formal parameter):
Formal parameters refer to the variables in parentheses after the function name. They are called formal parameters because they are instantiated (memory unit allocation) only when the function is called. Formal parameters are automatically destroyed after the function is called. Therefore, formal parameters are only valid in functions.

For example, the above function:

//Calculate the sum of two numbers
int jia(int c, int d)//Here c and d are formal parameters
//Formal parameters have their own storage space after instantiation, and have the same values as the actual parameters
{
	int sum = 0;
	sum = c + d;
	return sum;
}
int main()
{
	int a = 20;
	int b = 10;
	int sum = jia(a, b);//Here a and b are the actual parameters
	printf("%d", sum);
	return 0;
}


After the formal parameter is instantiated, it has its own address and the same value as the actual parameter. However, after the function exits, the address of the formal parameter will be destroyed, so we can generally think that:

After the formal parameter is instantiated, it is actually equivalent to a temporary copy of the argument.

5. Function call

Next is the function call:

In the above study, we saw that the parameter passed in the past can be a value or an address. What's the difference between the two?

In fact, function calls can be divided into value passing calls and address passing calls:

Call by value:
The formal parameters and arguments of the function occupy different memory blocks respectively, and the modification of the formal parameters will not affect the arguments.

Value passing call is to pass the value to the calling function. When we call the function, the temporary variables in the function will be destroyed and cannot be retained. If return does not return the value, the passed value will have no impact on the original function.

Address call:
Addressing call is a way to call a function by passing the memory address of the variable created outside the function to the function parameters.

Address transfer call is to transfer the address of the variable in the function to the calling function. This parameter transfer method can establish a true relationship between the function and the variables outside the function, that is, the variables outside the function can be directly operated inside the function.

We can simply understand the value transfer call and address transfer call as follows:

When we want to decorate the walls of our home, we tell the designer function what we think, and then the designer function draws the decoration draft in his own home. However, if he doesn't give me the final draft (i.e. return value), it won't affect the decoration in my home.

The address transfer call is to give my home address to the designer function and let him come to my home and design it in my home. Then I will decorate my wall directly and operate directly on my address. After the designer left, the walls in my house (address) have been decorated.

Of course, this is only for understanding, which is very different from the real call.

6. Nested call and chained access of functions

Nested call: functions can be organically combined. That is to say, you can call functions in the calling function.

Nested definitions are not allowed, but nested calls can be used.

Nested definition:

//Error code:
int main()
{
    void fun()//It is impossible to define a function within a function!
    {
        printf("123");
    }
    return 0;
}

That's right, Russian dolls have a small test:

Nested calls:

void second_fun()
{
	printf("a+b The value of is:");
}

int first_fun(int a, int b)
{
	int sum = 0; 
	second_fun();
	sum = a + b;
	
	return sum;

}

int main()
{
	int a = 20;
	int b = 10;
	int ret = first_fun(a,b);

	printf("%d", ret);
	return 0;
}

Another example:

#include <stdio.h>
void shuai()
{
    printf("I'm so handsome!\n");
}
void hao()
{
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        shuai();
    }
}
int main()
{
    hao();
    return 0;
}


Chained access is to take the return value of one function as the parameter of another function.

Yes, Russian dolls score twice:

int main()
{
	int len = strlen("abc");
	printf("%d\n", len);

	printf("%d\n", strlen("abc"));//Chain access
	//Output the return value of the strlen library function directly to the printf function
	//The printf output function is also a function
	return 0;
}

Now that you know what chain access is, let's take a look at this Code:

int main()
{
    printf("%d",printf("%d",prinft("%d",43)));
    //What is the output?
    return 0;
}

43? No, no, no, the answer is 4321. The printf function is also a function with a return value!

At this time, we can check in cplusplus:

Enter cplusplus to search printf, and then slide down to return value to view. Here, after success, that is, after successful output, the total number of written characters is returned. Here we know, that is, how many numbers are output, that is, the return value.

So the answer can be explained as:
Output: 4321
Find it in cplus plus: printf has a return value, and the return value is the number of output numbers. Therefore, the output of the innermost printf is 43, which outputs two numbers, and then returns the value to the second printf, and the output will be 2. Similarly, the output of the outermost printf is 1.

7. Declaration and definition of functions

Function declaration:
1. Tell the compiler what a function is called, what the parameters are and what the return type is. But it doesn't matter whether it exists or not.
2. The declaration of a function usually appears before the use of the function. To meet the requirements of declaration before use.
3. The function declaration is generally placed in the header file.

Function definition:
The definition of function refers to the specific implementation of the function and explains the function implementation of the function.

//Declaration of function
int Add(int x, int y);

//Definition of function Add
int Add(int x, int y)
{
 return x+y;
}

The declaration of the function is to tell the compiler that I have this function. Don't turn your face and don't recognize the code later. It must be declared before use, because the compiler starts working from top to bottom. If you use the function first, the compiler will report an error.

For example:

//Compile from top to bottom
int main()
{
	int a = 20;
	int b = 10;
	int ret = first_fun(a,b);
    //Unrecognized, function undefined

	printf("%d", ret);
	return 0;
}

int first_fun(int a, int b)
{
	int sum = 0; 
	second_fun();
	sum = a + b;
	
	return sum;
}

Correct code:

int first_fun(int a, int b);//Function declaration

int main()
{
	int a = 20;
	int b = 10;
	int ret = first_fun(a,b);//Declared available
	printf("%d", ret);
	return 0;
}

int first_fun(int a, int b)
{
	int sum = 0; 
	second_fun();
	sum = a + b;
	
	return sum;

}

Of course, you can directly put the calling function on the top, but when you need to write more code, we should write the function declaration in order to improve readability and block clarity. For example, we are making a three piece chess game in c language:

[C language] detailed explanation of Sanzi chess game

We can create a header file that contains the function declaration.

8. Function recursion

What is recursion?

The programming technique of program call itself is called recursion. The main way of thinking of recursion is to make big things small.

As an algorithm, recursion is widely used in programming languages. A process or function has a method to call itself directly or indirectly in its definition or description. It usually transforms a large and complex problem layer by layer into a smaller problem similar to the original problem. The recursive strategy can describe the multiple repeated calculations required in the problem-solving process with only a small number of programs, which greatly reduces the amount of code of the program.

Two necessary conditions for recursion:
1. There is a constraint. When this constraint is met, recursion will not continue.
2. Get closer and closer to this limit after each recursive call.

Let's take chestnuts for example:

Write such a code, receive an integer number (unsigned), and print each digit. For example, if 1234 is received, print 1, 2, 3, 4.

We can see that in the print function called in the main function, the print function calls itself internally, which is the programming skill of the program calling itself, which is recursion.

But sometimes recursion can be used without recursion, such as finding Fibonacci sequence:

int fib(int n)
{
    if (n <= 2)
        return 1;
    else
        return fib(n - 1) + fib(n - 2);
}

int main()
{
    int n = 0;
    printf("Please enter the Fibonacci number you want to know:>\n");
    scanf("%d", &n);
    int ret = fib(n);
    printf("The first%d The Fibonacci number of bits is%d",n, ret);
    return 0;
}

In this code, if I ask for the 50th Fibonacci number, it takes a lot of time. This is the problem we found. When using fib, if we want to calculate the 50th Fibonacci number, it takes a lot of time. The fib function is used to find the Fibonacci number of 10000 (regardless of the correctness of the result), and the program will crash.

Because many of our calculations are repeated! We can add the count variable to see how many times each number needs to be called:

int count = 0;//global variable
int fib(int n)
{
    if (n == 3)
        count++;
    if (n <= 2)
        return 1;
    else
        return fib(n - 1) + fib(n - 2);
}

int main()
{
    int n = 0;
    printf("Please enter the Fibonacci number you want to know:>\n");
    scanf("%d", &n);
    int ret = fib(n);
    printf("The first%d The Fibonacci number of bits is%d\n", n, ret);
    printf("loop%d second", &count);
    return 0;
}


Only 30 bits have been cycled 9281852 times, and 50 bits are unimaginable. So this code needs to be improved:

Rewrite recursion to non recursion.

int fib(int n)
{
    int ret;
    int pre_ret;
    int next_ret;
    ret = pre_ret = 1;
    while (n > 2)
    {
        n -= 1;
        next_ret = pre_ret;
        pre_ret = ret;
        ret = pre_ret + next_ret;
    }
    return ret;
}

int main()
{
    int n = 0;
    printf("Please enter the Fibonacci number you want to know:>\n");
    scanf("%d", &n);
    int ret = fib(n);
    printf("The first%d The Fibonacci number of bits is%d",n, ret);
    return 0;
}

So we conclude as follows:

  1. Many problems are explained in recursive form only because it is clearer than non recursive form.
  2. However, the iterative implementation of these problems is often more efficient than recursive implementation, although the readability of the code is slightly worse.
  3. When a problem is very complex and difficult to implement iteratively, the simplicity of recursive implementation can compensate for the runtime overhead.

There are many examples of recursion, such as the classic Hanoi tower game: Recursive Hanoi Tower

Well, that's all for the content of this article. Xiaobai's production is not easy. Please xdm correct the mistakes, pay attention to each other and make common progress.

There is another thing:

Keywords: C Programming

Added by JamesU2002 on Thu, 30 Dec 2021 07:08:19 +0200