[Basic knowledge of C language] program preprocessing operation

The translation environment and execution environment of the program

The first is a translation environment, in which source code is converted into executable machine instructions. The second is the execution environment, which is used to actually execute the code.

Translation environment

1` Each source file that composes a program is converted into object code (object code) through the compilation process.

2` Each object file is bundled together by the linker to form a single and complete executable program.

3`The linker will also introduce any function used by the program in the standard C function library, and it can search the programmer's personal library and link the functions it needs to the program.

Operating environment

The process of program execution:

  1. The program must be loaded into memory. In an environment with an operating system: Generally this is done by the operating system. In an independent environment, the loading of the program must be manually arranged, or it may be done by placing executable code into read-only memory.
  2. The execution of the program begins. Then call the main function.
  3. Start to execute the program code. At this time, the program will use a runtime stack to store the local variables and return address of the function. The program can also use static memory. Variables stored in static memory retain their values ​​throughout the execution of the program.
  4. Terminate the program. Terminate the main function normally; it may also terminate unexpectedly.

Detailed preprocessing

Predefined symbols
__FILE__      //进行编译的源文件
__LINE__     //文件当前的行号
__DATE__    //文件被编译的日期
__TIME__    //文件被编译的时间
__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义

These predefined symbols are built into the language.

#define

#define define identifier

#define fun function    //为function这个关键字取一个简短的名字

#define define macro

The #define mechanism includes a provision that allows parameters to be substituted into the text. This implementation is usually called a macro or definemacro.

For example, #define SQUARE(x) x*x
this macro accepts a parameter x. If the value of x is 5, the value of the macro is 5×5. Note that it is 5×5 instead of 25. The problem of symbol priority is involved here. It must be specifically analyzed in the program. If you want to avoid In this case, you only need to add parentheses to the entire macro definition expression during the macro definition.

#define substitution rules

1. When calling the macro, first check the parameters to see if it contains the symbols defined by #define. If they are, they are replaced first.
2. The replacement text is then inserted at the position of the original text in the program. For macros, the parameter names are replaced by their values.
3. Finally, scan the result file again to see if it contains any symbols defined by #define. If yes, repeat the above process.

Note:
1. Variables defined by other #define can appear in macro parameters and #define definitions. But for macros, recursion cannot occur.
2. When the preprocessor searches for symbols defined by #define, the contents of string constants are not searched.

Macro and function comparison

Macros are usually used to perform simple operations, such as finding the larger of two numbers

#define MAX(a,b) ((a)>(b)?(a):(b))

Then why not use functions to accomplish this task?
There are two reasons:

1. It may take more time to call functions and return codes from functions than to actually perform this small calculation work, so macros are
better than functions in terms of program size and speed.
2. More importantly, the parameters of the function must be declared as a specific type. So functions can only be used on expressions of the appropriate type. On the contrary, how can this macro be applied to the types that can be compared with >, such as integers, long integers, and floating-point types. Macros are type independent.

Of course, compared with macros, functions also have disadvantages:

  1. Every time a macro is used, a copy of the macro definition code will be inserted into the program. Unless the macro is relatively short, it may greatly increase the length of the program.
  2. Macros cannot be debugged.
  3. Since macros are not type-independent, they are not rigorous enough.
  4. Macros may cause problems with operator precedence, making the process prone to errors.
    Macros can sometimes do things that functions cannot. For example: Macro parameters can have types, but functions cannot.
Comparison of macros and functions
Attributes #define defined macro function
Code length Every time it is used, the macro code will be inserted into the program. Except for very small macros, the length of the program will increase significantly. The code of the function only appears in one place, and every time the function is used, the same code in that place is called
Execution speed Faster There is additional overhead for function calls and returns, so it is relatively slow
Operator precedence The evaluation of macro parameters is in the context of all range expressions. Unless parentheses are added, the precedence of adjacent operators may have unpredictable consequences. Therefore, it is recommended to add parentheses when writing macros. Function parameters are evaluated only once when the function is called, and its result value is passed to the function, and the evaluation result of the expression is easier to predict
Parameters with side effects Parameters may be replaced in multiple locations in the macro body, so parameter evaluation with side effects may produce unexpected results Function parameters are only evaluated once when passing parameters, and the results are easier to control
Parameter Type The parameter of the macro has nothing to do with the type, as long as the operation of the parameter is legal, it can use any parameter type The parameter type of the function is related to the type. If the parameter type is different, different functions are required, even if their tasks are the same.
debugging Macros are inconvenient to debug because they are replaced during pre-compilation Functions can be debugged statement by statement
Recursion Macros cannot be recursive Functions can be recursive

Guess you like

Origin blog.csdn.net/weixin_43962381/article/details/110343414