Table of contents
First, the program environment
1. The translation environment of the program
Program compilation and linking
2. The operating environment of the program
Two, preprocessing instructions
Usage 2: #define defines a macro
Comparison of pros and cons of macros and functions
How to solve multiple inclusions of header files?
First, the program environment
The first is the translation environment , where source code is converted into executable machine instructions.The second is the execution environment , which is used to actually execute the code.
1. The translation environment of the program
Program compilation and linking
The program is converted from source code that can be recognized by humans into a binary language that can be recognized by machines. The process is roughly as follows:
Among them, note:
- Each source file that makes up a program is converted into object code ( object code ) separately through the compilation process .
- Each object file is bundled together by a linker ( linker ) to form a single and complete executable program.
- The linker also imports any functions in the standard C library used by the program , and it can search the programmer's personal library and link the functions it needs into the program.
The detailed steps and the functions of each step are shown in the figure:
Once we've translated into machine language, it's ready to run.
2. The operating environment of the program
1. The program must be loaded into memory. In an environment with an operating system: Generally this is done by the operating system. In a standalone environment, program loading must be arranged manually, possibly by placing executable code into read-only memory.2. The execution of the program starts. Then call the main function.3. Start executing the program code. At this time, the program will use a runtime stack ( stack ) to store the local variables and return address of the function. Programs can also use static memory, and variables stored in static memory retain their values throughout the execution of the program.4. Terminate the program. Normal termination of the main function; unexpected termination is also possible.
Two, preprocessing instructions
predefined symbols
__FILE__ // source file for compilation__LINE__ // The current line number of the file__DATE__ // The date the file was compiled__TIME__ // The time when the file was compiled__STDC__ // If the compiler follows ANSI C , its value is 1 , otherwise it is undefined
like:
printf ( "file:%s line:%d\n" , __FILE__ , __LINE__ );// The first one will print the path of the source file; the second one will print the line number where this code is located
1. #define
Here is the #define we are most familiar with,
Usage 1: #define name stuff
#define k 20 // define a constant
Usage 2: #define defines a macro
Here is how the macro is declared:
#define name( parament - list ) stuff where parament - list is a comma-separated list of symbols that may appear in stuff.
#define text(x) 2 * x
Error-prone points:
#define SQUARE( x ) x * x // correct way of writing
#define text(x, y) x + y // High-risk code, very error-prone// For example: printf("%d", 2 * text(2, 3)); // The output is: 7 and what you want is 10, so the correct writing should be#define text(x, y) ((x) + (y))// So macro definitions used to evaluate numeric expressions should be parenthesized in this way to avoid the operator or parameter in the macro when using the macroUnexpected interactions between proximity operators .
1. Other variables defined by #define can appear in macro parameters and #define definitions. But with macros, recursion cannot occur .2. When the preprocessor searches for symbols defined by #defifine , the content of the string constant is not searched .
Comparison of pros and cons of macros and functions
(Note: widescreen viewing is recommended )
Attribute #define defines the macro functionCode Length Macro code is inserted into the program each time it is used. Except for very small macros, every time this function is used , the length of the program will be greatly increased by calling the same code at that place; the function code only appears in one place;
Execution speed Faster There is additional overhead for function calls and returns, so it is relatively slowOperator precedence Macro parameters are evaluated in the context of all surrounding expressions, function parameters are only evaluated once when the function is called, and its resulting value is passedUnless parenthesized, the precedence of the proximity operator may be given to the function. The result of evaluating an expression is more predictable.Unforeseen consequences, so it is recommended to have more parentheses when writing macros.Parameters with side effects may be replaced in multiple positions in the macro body, so parameter function parameters with side effects are only evaluated once when passing parameters, and the result is easier to control.Evaluation of the number of arguments may produce unpredictable results.Parameter type The parameters of the macro have nothing to do with the type. As long as the operation on the parameters is legal, it can be used. The parameters of the function are related to the type. If the types of the parameters different, different functions are required, even if the tasks they perform are different. of.to be used for any parameter type.Debugging Macros are inconvenient to debug, functions can be debugged statement by statementRecursion Macros cannot be recursive Functions can be recursive
2. # and ##
# function
First let's look at this code:
char* p = "hello ""bit\n";
printf("hello ""bit\n");
printf("%s\n", p);
From the results, we will find that the hello bit is printed. We found that strings are characterized by automatic connection .
Another trick is: Use # to turn a macro parameter into a corresponding string .
for example:
The first one: #define text(x) printf("I " "x" "China\n"); //parameter x needs to be a string
The second type: #define text(x) printf("I "#x"China\n"); // if x is also a string
## Functions:
#define ADD_TO_SUM(num, value)sum##num += value;...ADD_TO_SUM(5, 10);// The function is: add 10 to sum5 .
3. #undef:
#undef NAME //If an existing name needs to be redefined, its old name must be removed first.
4. Conditional compilation
#include <stdio.h>
#define max 2
int main()
{
#if max == 1
printf("hehe\n"); // 不编译
#elif max == 2
printf("baba\n"); // 编译
#else
printf("gungun\n"); // 不编译
#endif // 1
return 0;
}
5. #include
#include <stdio.h>#include "text.h" // self-built header file
There are two types of "" and <>, which are actually two search strategies :
- "" : First search in the directory where the source file is located . If the header file is not found, the compiler will search for the header file in the standard location just like searching for the library function header file. If not found, a compilation error will be prompted.
- <> : Find the header file and go to the standard path to search directly. If it cannot find it, it will prompt a compilation error. (The installation path that comes with the library file)
In this way, can it be said that the form of "" can also be used for library files? The answer is yes, yes, but the efficiency of searching in this way is lower. Of course, it is not easy to distinguish whether it is a library file or a local file.
How to solve multiple inclusions of header files?
Solution:
- Advanced: add #pragma once at the beginning of the header file
#pragma once
- Add manually: at the beginning of the header file
#ifndef _text_h_ // 没定义 返回1;否则返回0,结束编译
#define _text_h_
// ....... 各种包含头文件,函数声明
int k(int x, int y);
// .......
#endif // !_text_h_