当前位置:网站首页>C language program environment and preprocessing
C language program environment and preprocessing
2022-07-24 23:44:00 【Early snow in Shaoguang】
Program environment and preprocessing
`
List of articles
Program translation environment and execution environment
stay ANSIC In any implementation of , There are two different environments
The first 1 One is the translation environment , In this environment, source code is converted into executable machine instructions . The first 2 One is the execution environment , It's used to actually execute code
Translation environment

- Each source file constituting a program is converted into object code through the compilation process (object code).
- Each target file is linked by a linker (linker) Tied together , Form a single and complete executable program .
- Linkers also introduce standards C Any function in the function library used by the program , And it can search the programmer's personal library , Link the functions it needs to the program
Several stages of compilation

- Preprocessing Options gcc -E test.c -o test.i
Stop after the pretreatment is complete , All the results after pretreatment are put in test.i In file . - compile Options gcc -S test.c
Stop when the compilation is complete , The results are stored in test.s in . - assembly gcc -c test.c
Stop when the assembly is finished , The results are stored in test.o in .
Running environment
The process of program execution :
- The program must be loaded into memory . In an operating system environment : This is usually done by the operating system . In an independent environment , The loading of the program must be arranged manually , It can also be done by putting executable code into read-only memory .
- The execution of the procedure begins . And then I call main function .
- Start executing program code . At this point, the program will use a runtime stack (stack), Store function local variables and return address . Programs can also use static (static) Memory , Variables stored in static memory retain their values throughout the execution of the program .
- To terminate the program . Normal termination main function ; It could be an accidental termination .
Preprocessing
2.1 Predefined symbols
__FILE__ // Source files to compile
__LINE__ // The current line number of the file
__DATE__ // The date the file was compiled
__TIME__ // When the file was compiled
__STDC__ // If the compiler follows ANSI C, Its value is 1, Otherwise, it is not defined
These predefined symbols are language built-in types
stay VS In the compiler ,
__STDC__
Is not supported , therefore VS The compiler does not support __STDC__ That is, it does not support ANSIC, stay gcc Is supported by ,, So it's usually gcc Shall prevail .
What is the use of predefined symbols , for example : You can log ;
2.2#define
#define Define identifier
grammar :
#define name stuff
Here's a chestnut
#define MAX 1000
#define reg register // by register This keyword , Create a short name
#define do_forever for(;;) // Replace an implementation with a more vivid symbol
#define CASE break;case // Writing case Automatically put break write .
// If you define stuff Too long , It can be divided into several lines , Except for the last line , Add a backslash after each line ( Line continuation operator ).
#define DEBUG_PRINT printf("file:%s\tline:%d\t \ date:%s\ttime:%s\n" ,\ __FILE__,__LINE__ , \ __DATE__,__TIME__ )
stay define When defining identifiers , It is recommended not to add ;( A semicolon ), This is prone to errors
#define Defining macro
#defineThe mechanism includes a provision , Allow parameters to be replaced with text , This implementation is often referred to as macro (macro) or Defining macro (define macro)
#define name( parament-list ) stuff
The left parenthesis of the argument list must be the same as name Next door neighbor . If there is any gap between the two , The parameter list will be interpreted as stuff Part of
When defining macros, you must pay attention to the priority ;
#include <stdio.h>
#define SQUARE( x ) x * x
int main()
{
int r = SQUARE(5);
//r = 5*5;
// There are defects here :
int a = SQUARE(5+1);
// Think it's :a = (5+1)*(5+1)? error , The expression resulting from the substitution does not evaluate in the expected order
//a = 5+1*5+1 = 11
// Add two parentheses to the macro definition , This problem is easily solved :
return 0;
}
The value of a macro is not calculated and passed as a function , It's a replacement , Through the example above , We can see that if we don't add brackets, it is likely that the calculation results will not meet the expectations due to the priority problem ;
It is suggested that brackets should also be added to the whole , Because it may cause the same problem , Here we take a pear :
#include <stdio.h>
#define DOUBLE(x) (x)+(x)
int main()
{
int r = 10 * DOUBLE(3);
printf("%d\n", r);
return 0;
}
The result is 33
#include <stdio.h>
#define DOUBLE(x) ((x)+(x))
int main()
{
int r = 10 * DOUBLE(3);
printf("%d\n", r);
return 0;
}
The result is :60
One is the bracketed version of the whole , One is the unsupported version ; But the results are very different , To analyze :
Macros are replaced in the preprocessing stage , Let's replace :
int r = 10*(3)+(3);
If there are no parentheses, multiplication will be combined first , Then combine addition ;
int r = 10*((3)+(3));
When the whole is bracketed , We can see , It is to add first and then multiply ;
therefore :
So the macro definitions used to evaluate numeric expressions should be bracketed in this way , Avoid unexpected interactions between operators in parameters or adjacent operators when using macros
#define Replacement rules
As mentioned above ,#define It's replacement , Next, let's talk about the replacement rules :
Extend... In a program #define When defining symbols and macros , There are several steps involved .
- When calling a macro , First, check the parameters , See if it contains any information from #define Defined symbols . If it is , They are replaced first .
- The replacement text is then inserted into the program at the location of the original text . For macros , Parameter names are replaced by their values .
- Last , Scan the result file again , See if it contains any information from #define Defined symbols . If it is , Repeat the above process .
Be careful
Macro parameters and #define Other... Can appear in the definition #define Defined symbols . But for macros , No recursion .
When the preprocessor searches #define When defining symbols , The contents of string constants are not searched .
# and ##
Strings have the characteristics of automatic connection .
#include <stdio.h>
int main()
{
int a = 10;
printf("the value of " #N " is "FORMAT"\n",N);
float f = 3.14f;
printf("the value of " #N " is "FORMAT"\n",N);
return 0;
}
Let's look at this code , First of all ,printf() This function , We output different types , At this time, it is impossible to encapsulate functions , But we know that macros do not check the type , Can we write like this :
#include <stdio.h>
#define PRINT(N,FORMAT) printf("the value of " #N " is "FORMAT"\n",N)
int main()
{
int a = 10;
PRINT(a, "%d");
float f = 3.14f;
PRINT(f, "%lf");
return 0;
}
#N What is it? ?
# Is to change a macro parameter into the corresponding string
The above code outputs :
## The role of :
## You can combine the symbols on both sides of it into one symbol .
It allows macro definitions to create identifiers from detached pieces of text .
#define ADD_TO_SUM(num, value) \ sum##num += value;
...
ADD_TO_SUM(5, 10);// Role is : to sum5 increase 10.
Such a connection must produce a legal identifier . Otherwise the result is undefined .
Macro parameters with side effects
When macro parameters appear more than once in the macro definition , If the parameter has side effects , Then when you use this macro, you may
There is danger , Lead to unpredictable consequences . The side effect is the permanent effect of expression evaluation .
for example
x+1;// No side effects
x++;// With side effects
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
...
x = 5;
y = 8;
z = MAX(x++, y++);
printf("x=%d y=%d z=%d\n", x, y, z);// What is the result of the output ?
It is replaced after pretreatment :
z = ( (x++) > (y++) ? (x++) : (y++));
result :
x=6
y=10
z=9
Macro and function comparison
The advantages of macro :
- The code used to call and return from the function may take more time than actually performing this small computation .
therefore Macros are better than functions in terms of program size and speed . - More importantly, the parameters of a function must be declared as specific types .
So functions can only be used on expressions of the right type . On the contrary, how can this macro be applied to shaping 、 Long integer 、 Floating point type can be used for > To compare the types of . Macros are type independent .
The disadvantages of macro : Of course, compared with functions, macros also have disadvantages :
- Every time you use a macro , A macro defined code will be inserted into the program . Unless the macro is short , Otherwise, the length of the program may be greatly increased .
- Macros can't be debugged .
- Macro is type independent , It's not rigorous enough .
- Macros can cause operator priority problems , It is easy for Cheng to make mistakes .
| Belong to sex | #define Defining macro | function |
|---|---|---|
| Code length | Every time I use it , Macro code is inserted into the program . Except for very small macros , The length of the program will increase significantly | Function code only appears in one place ; Every time you use this function , Call the same code in that place |
| Execution speed | faster | There is an extra cost of calling and returning functions , So it's relatively slow |
| Operator priority | Macro parameters are evaluated in the context of all surrounding expressions , Unless you put parentheses , Otherwise, the priority of adjacent operators may have unpredictable consequences , Therefore, it is recommended that macros be written with more parentheses . | Function parameters are evaluated only once when the function is called , Its result value is passed to the function . The evaluation of expressions is easier to predict . |
| Parameters with side effects | Parameters may be replaced at multiple locations in the macro body , Therefore, parameter evaluation with side effects may produce unpredictable results | Function parameters are evaluated only once when passing parameters , The result is easier to control . |
| Parameter type | Macro parameters are type independent , As long as the operation on parameters is legal , It can be used for any parameter type . | The arguments to the function are type dependent , If the type of parameter is different , You need different functions , Even if they perform different tasks . |
| debugging | Macros are inconvenient to debug | Functions can be debugged statement by statement |
| recursive | Macros cannot be recursive | Functions are recursive |
Naming conventions
It's just an agreement, commonly known as , Not mandatory , But it's best ;
Capitalize all macro names
Do not capitalize all function names
2.3#undef
This instruction is used to remove a macro definition .
#undef NAME
// If an existing name needs to be redefined , Then its old name must first be removed
2.4 Conditional compilation
When compiling a program, if we want to translate a statement ( A set of statements ) It's convenient to compile or discard . Because we have conditional compilation instructions .
Debugging code , It's a pity , Reservation is in the way , So we can selectively compile
Common conditional compilation instructions
1.
#if Constant expression
//...
#endif
// Constant expressions are evaluated by the preprocessor .
Such as :
#define __DEBUG__ 1
#if __DEBUG__
//..
#endif
2. Conditional compilation of multiple branches
#if Constant expression
//...
#elif Constant expression
//...
#else
//...
#endif
3. Judge whether it is defined
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
4. Nested instruction
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endif
2.5 File contains
We already know , #include Instruction can cause another file to be compiled . It's like it actually appears in #include It's the same place as the command .
It's a simple alternative :
The preprocessor first removes this instruction , And replace... With the contents of the containing file .
Such a source file is contained 10 Time , So it's actually compiled 10 Time .
- The local file contains
#include "filename"
- The library file contains
#include <filename.h>
Look up the header file and go directly to the standard path , If no compilation error is found .
Is it possible to say , For library files, you can also use “” The form of includes ?
The answer is yes , Sure .
But this is less efficient , Of course, it is not easy to distinguish between library files and local files
If the nest contains , When the file is preprocessed, the code will be redundant , If you say , Just be careful when I include ?
But sometimes :
This may still include , therefore
On each header file :
#ifndef __TEST_H__
#define __TEST_H__
// Content of header file
#endif //__TEST_H__
perhaps
#pragma once
You can avoid the repeated introduction of header files .
边栏推荐
- JS ------ Chapter 5 functions and events
- Implementation of cat and dog data set classification experiment based on tensorflow and keras convolutional neural network
- Bug summary
- Talk about how redis handles requests
- 必会面试题:1.浅拷贝和深拷贝_浅拷贝
- Value driven provides the core driving force for the transformation of commercial BP - BP realization under business scenarios - Commercial BP sharing
- Paper time review MB2: build a behavior model for autonomous databases
- Google Earth engine - the use of the neighborhood tobands function
- 指针与数组
- Vite3.0 has been released, can you still roll it (list of new features)
猜你喜欢

Old Du servlet JSP

Development direction and problems of optaplanner

Notes of Teacher Li Hongyi's 2020 in-depth learning series 9

给生活加点惊喜,做创意生活的原型设计师丨编程挑战赛 x 选手分享

Coding builds an image, inherits the self built basic image, and reports an error unauthorized: invalid credential Please confirm that you have entered the correct user name and password.

Paper time review MB2: build a behavior model for autonomous databases

Go基础笔记_4_map

JS ------ Chapter 5 functions and events

凸优化基础知识

Opengauss kernel analysis: query rewriting
随机推荐
Development direction and problems of optaplanner
买收益百分之6的理财产品,需要开户吗?
Browser cache
芯片的功耗
Lidar obstacle detection and tracking: CUDA European clustering
Efficiency increased by 98%! AI weapon behind operation and maintenance inspection of high altitude photovoltaic power station
NVIDIA inspector detailed instructions
MATLAB basic grammar (II)
网上怎么炒股手机上炒股安全吗
Analysis of WPF multi finger application development
Go基础笔记_4_map
Only by learning these JMeter plug-ins can we design complex performance test scenarios
[zero basis] SQL injection for PHP code audit
Notes of Teacher Li Hongyi's 2020 in-depth learning series 9
多线程&高并发(全网最新:面试题 + 导图 + 笔记)面试手稳心不慌
Notes of Teacher Li Hongyi's 2020 in-depth learning series 6
Mandatory interview questions: 1. shallow copy and deep copy_ Shallow copy
Answers to some problems encountered in the process of Xperia XZ (f8332) brushing and root
激光雷达障碍物检测与追踪实战——cuda版欧式聚类
Network Security Learning (IV) user and group management, NTFS