On the execution efficiency of C language code

The execution efficiency that we usually talk about is the system overhead generated by using the same algorithm to complete the same calculation under the same input conditions. At present, we generally pay more attention to the execution time overhead. Code written in all languages ​​will eventually run and must be converted into machine code. It is more efficient to accomplish the same thing in less time.

Let's talk about how to improve the execution efficiency of the C language program.

1. Try to avoid calling delay functions

 

A program without an operating system can only be executed cyclically in while (1). If you call a large amount of delay in it, it will consume CPU resources. The delay is equivalent to letting it rest here, only interrupted Only the inside will be executed. If you just do a program that LED flashes once a second, it is very simple, you can directly call the delay function, but in actual projects, there are often many things to do in the big loop, not for occasions with high real-time requirements Too.

 

In order to avoid the use of delay, you can use the timer interrupt to generate a flag bit. When the time flag bit is set, you only need to detect the flag bit in the main program, set it to execute once, and then clear the flag. I will do other things at other times instead of waiting here. The best example is the display of the nixie tube, which uses the interrupt tone display. Then there is the key detection. The general procedure is to do while (! Key) to wait for the key to be released. If the key is kept pressed, the following program will never get run and die here. In fact, you can do a key logo to detect the drop Edge and rising edges can avoid this problem.

2. The code should be as concise as possible to avoid duplication

 

I saw the part of the code displayed on the digital tube written in the book that learned MCU in 10 days, selected a bit, and then sent the data, then selected a bit, and then sent the data, and finished it in turn. The code repetition rate is too high, which not only takes up too much class memory, but also has poor execution efficiency and poor readability. It only implements the function. The actual programming can be a loop, for loop or while loop. Such code looks more level.

3. Reasonable use of macro definitions

 

If a variable or register is frequently used in the program, you can use the macro definition to define a new name instead. This advantage is convenient for modification. For example, P1 connected to the data terminal bus of the LCD. Now you want to change to P0, then you only need to modify the macro definition here. When the compiler compiles, it will automatically replace the defined name with the actual The name.

4. Use the smallest possible data type

 

For example, the value range of a variable is 0 ~ 255, then it is defined as unsignedchar, of course, it can also be defined as unsignedint, but this causes a waste of memory, and the operation efficiency is lower.

 

If the data does not have a negative number, try to define it as an unsigned type. You should try to avoid being defined as a floating-point data type or a double-precision (8-byte) type. These two types consume a lot of CPU resources when computing.

 

For example, the collection voltage range is 0-5v, accurate to three decimal places, you can expand the collected data by 1000 times, even if the maximum is only 5000, then collect several times to make a filtering algorithm, and finally only need to calculate the voltage It is enough to add a decimal point after the first digit, and the variable is defined as an unsignedint variable.

5. Avoid using multiplication and division

 

Multiplication and division consumes CPU resources. Looking at the assembly code, you will find that a multiplication and division operation will compile 10 or even dozens of lines of code. If it is multiplied by or divided by 2 to the nth power, it can be implemented with << or >>. This shift operation is already calculated at compile time, so the code is very simple and the operation efficiency is high. But you need to pay special attention to the priority of operators.

 

6. Try to use compound assignment operators

 

What is the difference between the two expressions a = a + b and a + = b?

 

The former is to calculate the value of a + b first, and then save it to the ACC register, and then assign the value of the ACC register to a. The latter directly assigns the value of a + b to a, saving one step. Although only one instruction is saved, what about when this operation loops thousands of times and tens of thousands of times? Then the effect is obvious.

 

Like other-=, * =, / =,% =, etc. are the same.

7. Try not to define global variables

 

First look at the similarities and differences between local variables, global variables, static local variables, and static global variables.

 

▶ Local variables:

Variables defined in a function or compound statement are allocated storage units in the dynamic storage area, dynamically allocated when called, and automatically released when the function or compound statement ends.

 

▶ Static local variables:

When a local variable is defined in a function, if the static declaration is added, the variable is a static local variable, and the storage unit is allocated in the static storage area, and is not released during the running of the program; static local variables can only be used in the function; Static local variables are assigned at compile time (if no assignment is made at the time of definition, the default assignment is 0 (for numeric variables) or null characters (for character variables)); static local variables are not automatically released after the function call ends , Retain the value after the function call ends.

 

▶ Global variables:

Variables defined outside the function are called global variables; global variables are allocated to storage units in the static storage area, and are not released during program operation. The functions in the file can call the global variable, and the functions in other files call the global variable. Need to add extern statement.

 

▶ Static global variables:

When a variable is defined outside the function, if the staTIc statement is added, the variable is a static global variable; the static global variable is allocated to a storage unit in the static storage area and is not released during program execution. The static global variable is assigned at compile time (if If no assignment processing is performed during the definition, the default assignment value is 0 (for numeric variables) or null characters (for character variables); it can only be used in the current file.

 

▶ Summary:

Under normal circumstances, it is defined as a local variable, which not only runs more efficiently, but also is easy to transplant. Local variables are mostly located in registers inside the MCU. In most MCUs, the operation speed of using registers is faster than data storage, and the instructions are more and more flexible, which is conducive to generating higher-quality code, and the registers occupied by local variables And data storage can be reused in different modules.

 

When you need to use variables in an interrupt, you need to define them as global variables and add volaTIle to prevent compiler optimization. If the data is read-only, such as the broken code of the digital tube, the Chinese character modulo font library needs to be placed in the ROM, so that RAM can be saved, the 51 single-chip is added with code, and the more advanced single-chip is added with const modification.

8. Choose the right algorithm and data structure

 

You should be familiar with the algorithm language and know the advantages and disadvantages of various algorithms. For specific information, please refer to the corresponding reference materials, which are introduced in many computer books. Replacing the slower sequential search method with a faster binary search or out-of-order search method, and inserting or bubble sorting with quick sort, merge sort or root sort can greatly improve the efficiency of program execution. It is also important to choose a suitable data structure. A pointer is a variable containing an address, and the variable pointed to by him can be addressed. Using a pointer can easily move from one variable to the next variable, so it is particularly suitable for the operation of a large number of variables. Arrays and pointer statements have a very close relationship. Generally speaking, pointers are more flexible and concise, while arrays are more intuitive and easy to understand. For most compilers, the use of pointers is shorter than the code generated using arrays, and the execution efficiency is higher. In Keil, on the other hand, the code generated using an array is shorter than the pointer used.

9. Use conditional compilation

 

In general, when compiling a C language program, all programs participate in the compilation, but sometimes it is hoped that some of the content will be compiled only when certain conditions are met. This is conditional compilation. Conditional compilation can choose different compilation scopes according to the actual situation, thereby generating different codes.

 

10. Embedding compilation-killer translation

 

Assembly language is the most efficient computer language. In general project development, C language is generally used for development, because embedding assembly will affect the portability and readability of the platform. The assembly instructions of different platforms are incompatible. But for some persistent programmers who require the program to get the ultimate efficiency of running, they all embed assembly in C language, that is, "hybrid programming".

Published 13 original articles · praised 4 · visits 767

Guess you like

Origin blog.csdn.net/yuechifanfan/article/details/105570128