Little Gray Talks About Functions

1. What is a function?

insert image description here

  C语言函数是一种函数,用来编译C语言,
一般包括字符库函数,数学函数,目录函数,
进程函数,诊断函数,操作函数等

2. Library functions and custom functions

(1) Library functions
Library functions are a way to encapsulate functions into libraries for users to use. The method is to compile some commonly used functions into a file for different people to call. When calling the corresponding function, add the file name where it is located with #include<>. Usually placed in the lib file.
For example `

#include<math.h>  
//数学函数:包括常用的三角函数、指数和对数函数等。例如sqrt(开平方),pow(x的y次方)等。

#include<string.h>  
//字符串函数:于字符串操作函数:strcat,strchr,strcmp,strcpy,strlen,strstr等。

#include<time.h>
//时间函数:时间、日期和与系统有关的函数。对时间、日期的操作和设置计算机系统状态等。

A brief summary, the library functions commonly used in C language are:
IO function ,
string operation function ,
character operation function ,
memory operation function
, time/date function,
mathematical function
, other library functions

(2) Custom Functions
If the library functions can do everything, what should the programmer do?
insert image description here

So more important is the custom function. Like library functions, custom functions have function names, return value types, and function parameters. But the difference is that these are all designed by us. This gives programmers a lot of room to play.
The composition of the function:

 ret_type fun_name(para1, * )
{
    
    
 statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1    函数参数

Such as writing a function to add

int My_Add(int a, int b)
{
    
    
  int c=0;
  c=a+b;
  return c;
}
//int 表示返回类型为整形,My_Add为函数名
//int a 和int b 表示参数类型为整形
//return c表示将c以整形返回

3. Function parameters

(1) Actual parameters (actual parameters):
The parameters that are actually passed to the function are called actual parameters.
Arguments can be: constants, variables, expressions, functions, etc. Regardless of the type of quantities the actual parameters are, they must have definite values ​​in order to pass those values ​​to the formal parameters when the function is called.
(2) Formal parameters (formal parameters):
Formal parameters refer to the variables in parentheses after the function name, because the formal parameters are only instantiated (allocated memory units) when the function is called, so they are called formal parameters. Formal parameters are automatically destroyed when the function call is complete. Therefore formal parameters are only valid within functions
.
**It should be noted that:** The data transfer that occurs in the function call is one-way, only the value of the actual parameter can be passed to the formal parameter, and the value of the formal parameter cannot be passed to the actual parameter in reverse; In other words, once the data transfer is completed, the actual parameter and the formal parameter are no longer related, so during the function call process, the change of the value of the formal parameter will not affect the actual parameter.

4. Function call:

(1) Call by value
The formal parameters and actual parameters of the function occupy different memory blocks respectively, and the modification of the formal parameters will not affect the actual parameters.
(2) Call
-by-reference Call-by-reference is a way to call a function by passing the memory address of the variable created outside the function to the function parameter.
This method of passing parameters allows the function to establish a real connection with the variables outside the function, that is, the function can directly operate the variables outside the function.

5. Nested Calls and Chained Access to Functions

Functions and functions can be combined according to actual needs, that is, they can call each other.
For example, the following code is a nested call of a function

#include <stdio.h>
void new_line()
{
    
    
 printf("hehe\n");
}
void three_line()
{
    
    
    int i = 0;
 for(i=0; i<3; i++)
   {
    
    
        new_line();
   }
}
int main()
{
    
    
 three_line();
 return 0; 
}

Nested calls are when a function calls another function (that is, function nesting allows one function to call another function). Functions can be called nested, but not nested definitions

6. 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 whether it exists or not is not determined by the function
    declaration.
  2. The declaration of a function generally appears before the use of the function. To satisfy the declaration before use.
  3. Function declarations are generally placed in header files.
    Function definition:
    The definition of a function refers to the specific implementation of the function, explaining the function implementation of the function.
    function declaration
#ifndef __TEST_H__
#define __TEST_H__
//函数的声明
int Add(int x, int y);

Definition of function: that is, to explain the realization of function function

//函数Add的实现
int Add(int x, int y) 
{
    
    
 return x+y; 
}

7. Function recursion

(1) What is recursion?
The programming technique in which a program calls itself is called recursion. Recursion as an algorithm is widely used in programming languages. A procedure or function in its definition or description has
a method of directly or indirectly calling itself, which usually transforms a large and complex problem into a smaller problem similar to the original problem to solve. The recursive strategy only A small number of programs can be used to describe the repeated calculations required for the problem-solving process, which greatly reduces the code amount of the program.
The main way of thinking about recursion is: make big things small
(2) Two necessary conditions for recursion
There are constraints, when the constraints are met, the recursion will not continue. It gets closer and closer to this limit after each recursive call.
Exercise
Take an integer value (unsigned) and print its bits in order.
For example:
input: 1234, output 1 2 3 4.
Reference code:

#include <stdio.h>
void print(int n) 
{
    
    
 if(n>9)
 {
    
    
 print(n/10);
 }
 printf("%d ", n%10);
}
int main()
{
    
    
 int num = 1234;
 print(num);
 return 0; 
 }

recursion and iteration

Exercise 2 : Find the factorial of n. (regardless of overflow)
reference code:

nt factorial(int n) 
{
    
    
 if(n <= 1)
 return 1;
 else
 return n * factorial(n-1);
}

Exercise 3:
Find the nth Fibonacci number. (regardless of overflow)
reference code:

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

But we found a problem ;
using the fib function is particularly time consuming if we want to calculate the 50th Fibonacci number.
Use the factorial function to find the factorial of 10000 (without considering the correctness of the result), the program will crash.
why?
We found that many calculations are actually repeated in the process of calling the fib function.
If we modify the code a bit:

int count = 0;//全局变量
int fib(int n) 
{
    
    
 if(n == 3)
 count++;
 if (n <= 2)         
 return 1;
    else
    return fib(n - 1) + fib(n - 2);
}

Finally, we output to see count, which is a very large value. So how can we improve?
When debugging the factorial function, if your parameter is relatively large, it will report an error: stack overflow (stack overflow) such information. The stack space allocated to the program by the system is limited, but if there is an infinite loop, or (dead recursion), it may lead to the continuous development of the stack space and eventually the exhaustion of the stack space. This phenomenon is called stack overflow. .
How to solve the above problem:

  1. Rewrite recursion to be non-recursive.
  2. Use static objects instead of nonstatic local objects. In the design of recursive functions, static objects can be used to replace
    nonstatic local objects (ie stack objects), which
    can not only reduce the overhead of generating and releasing nonstatic objects during each recursive call and return, but also
    save the recursive call's Intermediate state and can be accessed by
    various call layers.

The following code is used in a non-recursive way:

//求n的阶乘
int factorial(int n) 
{
    
    
        int result = 1;
        while (n > 1)
       {
    
    
             result *= n ;
             n -= 1;
       }
        return result; 
 }
//求第n个斐波那契数
int fib(int n) 
{
    
    
     int result;
     int pre_result;
     int next_older_result;
     result = pre_result = 1;
      while (n > 2)
     {
    
    
           n -= 1;
           next_older_result = pre_result;
           pre_result = result;
           result = pre_result + next_older_result;
     }
     return result; 
}

hint:

  1. Many problems are explained in recursive form simply because it is clearer than the non-recursive form.
  2. But iterative implementations of these problems tend to be more efficient than recursive implementations, although the code is slightly less readable.
  3. When a problem is too complex to implement iteratively, the simplicity of the recursive implementation can compensate for the runtime overhead it imposes
    .
    insert image description here
    insert image description here

Guess you like

Origin blog.csdn.net/qq_62316056/article/details/124112429