Catalog
1. Simple introductory functions
1. Write a function to find the maximum of two integers.
2. Write a function to exchange the contents of two integer variables.
1. Actual parameters (arguments)
2. Formal parameters (formal parameters)
3. Analysis of the actual and formal parameters of the first two functions
4. Declarations and Definitions of Functions
1. Two prerequisites for recursion
2. Print each of the integer values (unsigned) in order.
5. Find the nth Fibonacci number.
1. Simple introductory functions
1. Write a function to find the maximum of two integers.
#include <stdio.h> int get_max(int x, int y) { return (x>y)?(x):(y); } int main() { int num1 = 10; int num2 = 20; int max = get_max(num1, num2); printf("max = %d\n", max); return 0; }
2. Write a function to exchange the contents of two integer variables.
#include <stdio.h> //Implement as a function, but cannot complete the task void Swap1(int x, int y) { int tmp = 0; tmp = x; x = y; y = tmp; } //Correct version void Swap2(int* px, int* py) { int tmp = 0; tmp = *px; *px = *py; *py = tmp; } int main() { int num1 = 1; int num2 = 2; Swap1(num1, num2); printf("Swap1::num1 = %d num2 = %d\n", num1, num2); Swap2(&num1, &num2); printf("Swap2::num1 = %d num2 = %d\n", num1, num2); return 0; }
2. Parameters of functions
1. Actual parameters (arguments)
- The parameters that are actually passed to the function are called arguments.
- Arguments can be constants, variables, expressions, functions, and so on.
- No matter what type of quantity the arguments are, they must have definite values when making a function call so that they can be passed to the parameter.
2. Formal parameters (formal parameters)
- Formal parameters are variables in parentheses after the function name, because they are instantiated only during the call to a function (allocating memory units), so they are called formal parameters.
- Formal parameters are automatically destroyed when the function call is complete. Therefore, formal parameters are only valid in functions.
3. Analysis of the actual and formal parameters of the first two functions
The corresponding memory allocation for the code is as follows:
Here you can see that when the Swap1 function is called, x, y has its own space and the same content as the actual parameter. So we can simply think that the instantiation of a parameter is actually equivalent to a temporary copy of the argument.
3. Calls to Functions
1. Pass-by call
Function parameters and arguments occupy different memory blocks, and modification of the parameters will not affect the arguments.
2. Address Calls
Address call is a way of calling a function by passing the memory address of the variable created outside the function to the function parameter.
This way of passing parameters makes a real connection between the function and the variables outside the function, that is, the variables outside the function can be manipulated directly inside the function.
3. Nested Calls
#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; }
Note: Functions can be called nestedly, but cannot be defined nestedly.
4. Chain access
Take the return value of one function as the parameter of another function.
#include <stdio.h> #include <string.h> int main() { char arr[20] = "hello"; int ret = strlen(strcat(arr,"bit"));//Here's a description of the strlen function printf("%d\n", ret); return 0; } #include <stdio.h> int main() { printf("%d", printf("%d", printf("%d", 43))); //What is the result? //Note: The return value of the printf function is the number of characters printed on the screen return 0; }
4. Declarations and Definitions of Functions
1. Declaration
1. Tell the compiler what a function is called, what parameters are, and what return type is. But whether it exists or not is not determined by the function declaration.
2. Declarations of functions generally precede their use. To be satisfied, declare before use.
3. Declarations of functions are usually placed in header files.
2. Definition
The definition of a function refers to the concrete implementation of the function, which is the realization of the function.
Test. Contents of H Place the declaration of the function
#ifndef __TEST_H__ #define __TEST_H__ //Declaration of function int Add(int x, int y); #endif //__TEST_H__
Test. Contents of C Placement function implementation
#include "test.h" //Implementation of Function Add int Add(int x, int y) { return x+y; }
5. Function Recursion
1. Two prerequisites for recursion
- There is a restriction, and when that restriction is met, recursion does not continue.
- This limit gets closer and closer after each recursive call.
2. Print each of the integer values (unsigned) in order.
For example: input: 1234, output 1 2 3 4
#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; }
3. Writing a function does not allow you to create temporary variables to find the length of a string.
#incude <stdio.h> int Strlen(const char*str) { if(*str == '\0') return 0; else return 1+Strlen(str+1); } int main() { char *p = "abcdef"; int len = Strlen(p); printf("%d\n", len); return 0; }
4. Find the factorial of n.
int factorial(int n) { if(n <= 1) return 1; else return n * factorial(n-1); }
5. Find the nth Fibonacci number.
int fib(int n) { if (n <= 2) return 1; else return fib(n - 1) + fib(n - 2); }
But we found a problem:
This function of fib takes a lot of time if we want to calculate the 50th Fibonacci number. (
Using the factorial function to calculate the factorial of 10,000, regardless of the correctness of the result, the program crashes.
6. Reflective Improvement
So how can we improve it?
When debugging the factorial function, you will get an error if your parameter is large: stack overflow.
The stack space allocated by the system to a program is limited, but if there is an infinite loop, or (dead recursion), it may lead to a constant opening of stack space and eventual exhaustion of stack space, a phenomenon we call stack overflow.
How to solve the above problems:
- Override recursion to non-recursion.
- Use a static object instead of a nonstatic local object. In recursive function design, a static object can be used instead of a nonstatic local object (i.e., a stack object), which not only reduces the overhead of generating and releasing a nonstatic object each time a recursive call and return occurs, but also saves the intermediate state of a recursive call and can be accessed by various call layers.
Resolve first non-recursively
//Factorial of n int factorial(int n) { int result = 1; while (n > 1) { result *= n ; n -= 1; } return result; } //Find the nth Fibonacci Number 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; }