Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Analysis of preprocessing examples in C language Program Environment

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article introduces the knowledge of "pre-processing case analysis in C language program environment". Many people will encounter such a dilemma in the operation of actual cases. next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

I. Translation environment

The whole translation environment can be roughly drawn like this.

The following points need to be explained:

1. Each source file that makes up a program is converted to an object file separately through the compilation process (in Linux, the target file is suffixed with .o; in Windows, the target file suffix is .obj).

two。 Each object file is bundled together by a linker to form a single and complete executable program

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

Then it introduces the implementation of each step in the whole translation environment under the Linux system, as well as the function of each step.

Compilation can be divided into three parts:

(1) pre-processing: enter the instruction gcc-E test.c-o, and the test.c file will be changed into a test.i file. The purpose of this step is to include the header file (# include), delete comments, replace # define definition symbols, and other text operations (the preprocessing step will be described in detail below)

(2) compilation: enter the instruction gcc-S test.i, and the test.i file will be changed into a test.s file. The main function of this step is to convert the C language code into assembly code, which includes 4 steps: 1. Grammatical analysis; 2. Lexical analysis; 3. Semantic analysis; 4. Symbol summary

(3) assembler: enter the instruction gcc-c test.s, which will turn the test.s file into a test.o file. This step is to convert the assembly code into a binary instruction, which forms a symbol table, which prepares for the next link operation.

Multiple .c files go through the compilation process to form .o object files. When you want to perform a link, enter the instruction gcc test.o add.o-o test, which will turn the .o file into an executable file. The operation includes merging segment tables and symbol tables and repositioning. This step is mainly to check whether external symbols exist through the symbol table when multiple target files are connected. In this way, the operation of the whole translation environment is completed.

II. Execution environment

The execution process of the program can be divided into the following steps:

1. The program must be loaded into memory. In an environment with an operating system: it is generally done by the operating system. In a stand-alone environment, the loading of a program must be arranged manually or by placing read-only memory in executable code

two。 The execution of the program begins. The main function is then called

3. Start executing the program code. At this time, the program will use a runtime stack to store the local variables and return addresses of the function; the program can also use static memory, and variables stored in static memory will retain their values throughout the execution of the program.

4. Terminate the program. Terminating the main function, or unexpectedly

Third, pretreatment 1. Preprocessing symbol

In C, some preprocessing symbols are built into the language, such as:

_ _ FILE__ / / Source file compiled _ _ LINE__ / / current line number of the file _ _ DATE__ / / date the file was compiled _ _ TIME__ / / time the file was compiled _ _ STDC__ / / if the compiler complies with ANSI C, the value is 1, otherwise the 2. # define definition identifier is not defined

Identifiers defined by # define can be constants, simplified keywords, symbols, etc., such as:

# define M 10 / define constant # define reg register / / simplify keywords # define do_forever for (;) / / replace an implementation # define CASE break;case / / automatically write break when writing case statements

For # define definition identifiers, if the definition is too long, you can write it in several lines, adding'\'to every line except the last, for example:

# define DEBUG_PRINT printf ("file:%s\ tline:%d\ t\ date:%s\ ttime:%s\ n",\ _ _ FILE__,__LINE__ \ _ _ DATE__,__TIME__) 3. # define defines macros

In addition to the # define definition identifier, there is another provision in # define that allows parameters to be replaced into text, which in turn forms the # define definition macro. The declaration is as follows:

# define name (parament-list) stuff

The parament-list here is a symbol table separated by a comma, and they will also exist in the stuff in the actual code.

Among them, it is worth noting that:

1. The left parenthesis of the parameter list must be adjacent to name

two。 If there is any space between parament-list and stuff, the parameter list is annotated as part of stuff

Now that you understand how the # define definition macro is written, it's time for # define to define the replacement rules for the macro:

1. When invoking macros, first check the parameters to see if they contain any symbols defined by # define. If so, they are replaced first

two。 The replacement text is then inserted into the original text position in the program, and 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 so, repeat the above process

Therefore, after summing up the above rules, the conclusion is that if the # define definition macro is used to evaluate numeric expressions, you should add parentheses to avoid unpredictable interactions between operators in parameters or adjacent operators when using macros.

Of course, there are several other points to note about the use of # define:

1. Other # define defined symbols can appear in macro parameters and # define definitions, but for macros, there can be no recursion

two。 When the preprocessor searches for symbols defined by # define, the contents of the string constant are not searched

4. # and

For some cases where you want to insert a parameter into a string, we will use # to turn a macro parameter into a corresponding string. Here's an example:

If it is printed directly, because the string can be concatenated, it looks like this:

# include int main () {int a = 10; printf ("the value of"a"is% d\ n", a); return 0;}

Then, for defining macro parameters, this is what you should do:

# include # define PRINT (n) printf ("the value of" # n "is% d\ n", n) int main () {int a = 10; PRINT (a); return 0;}

In this way, the n in the string will change according to the value of the macro parameter.

The function of # # is to combine the symbols on both sides of it into a symbol. It allows macro definitions to create identifiers from separate segments of text. However, this connection must produce a legal identifier, otherwise it will report that the identifier is not defined.

5. Comparison between macros and functions

The advantages of macros: 1. When performing some small computing work, defining macros takes less time than calling functions and code returned from functions; 2. The parameters of the function must be declared as a specific type, and the two macro parameters are not used.

Macro's disadvantages: 1. Each time you use a macro, a copy of the code defined by the macro is inserted into the program. Unless the macro is relatively short, the length of the program may be greatly increased. 2. Macros cannot be debugged, but functions can; 3. Macros are sometimes not rigorous enough because they are not defined by types. 4. Macros may cause problems with the precedence of operators, resulting in error-prone programs

Attribute # define defines the macro function code length each time the macro code is used, the macro code is inserted into the program. Except for very small macros, the length of the program increases significantly. The function code appears in only one place. Every time you use this function, the same code in that place is called faster, which has the extra overhead of using the function and returning, so the operator priority macro parameter is evaluated in all surrounding expression contexts, unless parentheses are added, the priority of adjacent operators may have unpredictable consequences. Therefore, it is recommended that macros write more parentheses when the function parameter is evaluated only once when the function is called, and its result value is passed to the function. The evaluation result of the expression is easier to predict that parameter parameters with side effects may be replaced to multiple locations in the macro body, so parameter evaluation with side effects may produce unpredictable results. Function parameters are evaluated only once when parameters are passed. As a result, it is easier to control that the parameters of the parameter type macro are independent of the type, as long as the operation of the parameter is legal. It can be used in any parameter type function whose parameters are related to the type, and different parameters are required if the parameter types are different. even if the different debug macros of the tasks they perform are inconvenient to debug, the functions that can be debugged sentence by statement are recursive macros that cannot be recursive 6. Conditional compilation

Here are some compilation instructions:

1. # undef this directive is used to remove a macro definition

two。 The instruction is to determine which statement block should be executed

# if constant expression execution chunk # elif constant expression execution chunk # else execution chunk # endif

3. The instruction is to determine whether it is defined or not

# if define (symbol) if defined, execute this statement block or#ifdef symbol if defined, execute this statement block or#if! define (symbol) if not defined, execute this statement block or#ifndef symbol if not defined, execute this statement block

4. For conditional compilation instructions, they can also be nested, which is called nested instructions.

7. The file contains

When we compile some larger projects, or when multiple people work together on the same project, there may be repeated inclusion of header files, and if this is the case, it will greatly reduce the efficiency of the entire code runtime. Therefore, it is very important to avoid repeated inclusion of header files. So, how to avoid it? Here is a piece of code that can be used to avoid this:

# ifndef _ _ TEST_H__#define _ _ TEST_H__ write header file content # endif

This code can solve the problem of repeated inclusion of header files very well, but in fact, if it is compiled in the environment of VS, it will be automatically written at the beginning: # pragma once, this code can also solve the problem of repeated inclusion.

So, after solving the problem of repeated header file inclusion, let's introduce two ways of header file inclusion:

1. Header files enclosed in quotation marks, for example: # include "test.h". The search strategy of this header file is to first look in the directory where the source file is located. If the header file is not found, the compiler looks for the header file in the standard location just like the library function header file. If it can not be found, it will report an error directly.

two。 Include the header file in angle brackets, for example: # include. This way of inclusion is to proceed directly to the second step without the first step.

However, it can not be said that in order to be foolproof, all header files are included in quotation marks directly. In this case, sometimes the misuse of quotation marks in the case of angle brackets leads to a decline in the execution speed and efficiency of the program.

This is the end of the content of "case Analysis of preprocessing in C language Program Environment". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report