当前位置:网站首页>Preprocessing instruction define, do you really understand?
Preprocessing instruction define, do you really understand?
2022-07-24 01:10:00 【Earnest kitten】
Study C Language has been around for a while , Began to contact C Preprocessor and C library , Then I learned the explicit constants #define, I found that I knew too little before , Yes C The understanding of is far from enough , Make this summary :
Like other preprocessing instructions , Explicit constants #define Also to # As the beginning of a line .ANSI And later standards # The sign is preceded by a space or tab , And it's also allowed in # And the rest of the instruction .
Explicit constants :#define
example 1:
#define KE printf("E is %d\n",E)
As for the above code , Each row #define There are 3 Part of it is made up of , The first part (#define) It is the instruction itself , Also called macro ; The second part (KE) Is the selected abbreviation ; The third part (printf(“E is %d\n”,E)) Replacement list or replacement body .
Note the definition of macros : Spaces are not allowed in the name of a macro , To be followed C Naming rules for variables , Only characters can be used 、 Numbers and underlined _ The characters of , The first character cannot be a number .
Once the preprocessor finds an instance of the macro in the program , The macro will be replaced with a replacement body ( There are exceptions. ). The process of changing from a macro to the final replacement text is called Macro expansion . Can be in #define Line usage standard C notes , Each comment is replaced by a space .
example 1 It is also replaced in , But a new usage , Most of us only use macros to express explicit constants . From this statement, we can see that macros can also represent any string , Even express the whole C expression .
Be careful : although KE Is a string constant , But he only prints one named E The variable of . Because the compiler does not recognize all constant expressions at compile time ( Expressions that contain only constants ) evaluation , Therefore, the preprocessing will not carry out the actual calculation , Only replace , This process is performed at compile time .
example 2:
#define Y 4
#define KE Y*Y
// here KE = 4*4, Instead of computing , Only replace
A macro definition can also contain other macros ( Some compilers do not support this nesting function ), For example 3
example 3:
#define Y "X is %d.\n"
int x = 2;
printf(Y,x);
// This has become :printf("X is %d.\n",x); The corresponding string replaces Y.
// You can also use it :const char* y = "X is %d.\n"; Then you can put y As printf() The format string of .
Double quotation marks make the replaced string a string constant , The compiler stores the string in an array ending in a null character .
example 4:
#define Y "z"// Here we define a string (z\0)
#define H "I am a failure, I think it is now, I hope as a friend o\ f you must refueling"
// Adding a backslash character to the end of a line of macro definition can expand the line to the next line , But if the next line is with 1// When the lines are not aligned , The first 2 Spaces from lines to statements are also part of the string .
Another thing to note is that after the preprocessor finds the macro in the program , Replace with macro equivalent replacement text , If the replacement string also contains a macro , Then continue to replace the macro . The only exception is macros in double quotes .
In addition, from a technical point of view , You can think of the replacement of a macro as a symbolic string , Instead of character strings .C The preprocessor token is a separate token in the replacement body of the macro definition “ word ”. Separate these words with blanks .
for example 5:
example 5:
#define FRR 2*2 // The macro definition has 1 Marks :2*2 Sequence .
#define SIC 3 * 3 // The macro definition has 3 Marks :3、*、3.
When there are multiple spaces in the substitution , Character strings and token strings are handled differently . For example 5 Of #define SIC 3 * 3 , If the preprocessor interprets the replacement as a character string , 3 * 3 Replace SIC. The extra space is part of the substitution . If the preprocessor interprets the replacement as a token string , 3 * 3( Separate with a single space ) Replace SIC.
To make a long story short , Interpreting as a character string will treat spaces as part of the substitution , Interpreted as a tokenized string , Regard the space as the separator of each mark in the replacement .
#define FRR 2*2 // Yes 1 Marks
#define FRR 2 * 2 // Yes 3 Marks
It is obvious that the macro definitions in the above two sentences are different when redefining constants .
stay #define Parameters used in :
stay #define Using parameters in can create shapes and functions similar to Class function macro .
Actually, it looks like a function , Because such macros also use parentheses , And there can be one or more parameters in parentheses , Then these parameters appear in the replacement body .
example 6:
#define MEAN(X,Y) (((X)+(Y))/2) //MEAN(X,Y) As macro , In parentheses are macro parameters ,(((X)+(Y))/2) Is a substitute
int Z = 0;
Z = MEAN(2,3); // This looks very similar to function calls
The above code replacement behavior and function call look the same , But it is not , His two usages are completely different .
Next, explain the differences :
Before explanation , First look at some of the code :
example 7:
#define SQ(X) X*X
#define PR(X) printf("The result is %d.\n",X)
int main()
{
int x = 5;
int z;
printf("x = %d\n",X);
z = SQ(X);
printf("SQ(X):");
PR(z);
z = SQ(2);
printf("SQ(2):");
PR(z);
printf("SQ(x+2):");
PR(SQ(x+2));
printf("100/SQ(2):");
PR(100/SQ(2));
printf("x is %d.\n",x);
printf("SQ(++x):");
PR(SQ(++x));
printf("after incrementing,x is %x.\n",x);
return 0;
}
Of course, the above program is only explaining that macro parameters and function parameters are not exactly equal , The output values are as follows ( The output value may be completely different according to different compilers ):
The output result of the above code is :
x = 5;
SQ(X):The result is 25.
SQ(2):The result is 4.
SQ(X+2):The result is 17.
100/SQ(2):The result is 100.
x is 5.
SQ(++x):The result is 42.
after incrementing,x is 7.
The first two lines are consistent with the expected value , But the next result is a little strange , Program settings x yes 5, You might think SQ(x+2) Should be 77, namely 49. however , The output is 17, This is not a square value !
In fact, the reason is very simple , It's because the preprocessor doesn't do calculations 、 No evaluation , Replace only character sequences .
Preprocessor handle x Replace where it appears with x+2. therefore ,xx Turned into x+2x+2. If x by 5, Then the value of this expression is :
5+25+5 = 5+10+2 = 17!
The function call passes the value of the parameter to the function when the program runs . Macro calls pass parameter markers to the program before the compiler !
Of course , You can add a few parentheses , But this cannot solve all the problems .
If necessary, use enough parentheses to ensure the correct order of operations and combinations .
Even this cannot avoid the problem of the last case of the program .SQ(++x) Turned into ++x*++x, Increased twice x, Once before multiplication , Once after multiplication .
therefore , Try to avoid using x++ As macro parameters . Try not to use increment and decrement operators in macro definitions .
There is another use : Create a string with macro parameters # Operator
C Allow macro parameters in strings ,# As a preprocessing operator , You can convert tokens into strings . for example : if x Is a macro parameter , that #x Is to convert strings “x” The formal parameter name of . This process is called stringing .
example 8:
#define FRR(x) printf("The result "#x" is %d.\n",((x)*(x)))
int main()
{
int y = 5;
FRR(y);
FRR(2+4);
return 0;
}
Change the output of the program to :
The result y is 25.
The result 2+4 is 25.
Call the first macro , use “y” Replace “#x”, Call the second macro , use “2+4” Replace “#x”.
Finally, I have to mention the pre processor adhesive :## Operators and variable parameter macros :… and _ VA_ARGS _
And # Operators are similar to ,## The operator can be used in the replacement part of a function like macro . and ,## It can also be used as a replacement part of an object macro .## Operator combines two tokens into a token .
example 9:
#define KE(x) n##x
macro KE(4) Expand as n4. It should be noted that ## Operator combines tokens into a new identifier .
As for variable parameter macro :… and _ VA_ARGS In fact, it is also relatively simple .
Usually some functions accept a variable number of parameters . By writing the last parameter in the macro parameter list as an ellipsis ( namely :3 A little bit …) To achieve this function . In this case VA_ARGS _ It can be used in the replacement part , Indicates what the ellipsis stands for .
example 10:
#define PR(...) printf(_ _VA_ARGS_ _)
// Suppose you call the macro later
PR("hollo");
PR("The result "#x" is %d.\n",w,z);
For the first call ,_ VA_ARGS Begin to 1 Parameters "hollo".
For the second call ,VA_ARGS _ Begin to 3 Parameters "The result “#x” is %d.\n"、w、z.
Ellipsis can only replace the last macro parameter , You can't put it anywhere else .
summary :
1: Remember that no spaces are allowed in macro names , But you can have spaces in the replacement string .ANSI C Allow spaces in parameter lists .
2: Use parentheses to enclose the macro's parameters and the entire replacement body . This ensures that the enclosed part unfolds correctly .
3: Use capital letters to indicate the name of the macro function . This Convention is not as widely used as using capital letters to represent macro constants . however , Capital letters can remind programmers of , Possible side effects of macros .
4: If you plan to use macros to speed up your program , First of all, we need to determine whether using macros and functions will make a big difference . Macros that are used only once in a program cannot significantly reduce the running time of the program . Using macros in nested loops can help improve efficiency .
This article is my study C Most languages are borrowed 《C primer puls》 Written in a book .
If there is a mistake , Please correct me. .
边栏推荐
- Intelligent video monitoring solutions for elderly care institutions, using new technologies to help the intelligent supervision of nursing homes
- Source code installation and use of APIs IX
- Image processing 1:rgb888_ YCbCr444
- [untitled]
- Linkerd service grid survey notes
- Sparksql design and introduction, 220722,
- Axure implements addition, deletion, modification and query
- C language database: detailed description. Use the student management system to understand the operation of the database, which is simple and easy to understand.
- Notes: middle order traversal of binary trees (three solutions - recursion, iteration, Morris)
- Socket basic knowledge and various usage scenarios
猜你喜欢

IDEA设置 自动导包删无用包

Kubernetes deployment dashboard (visual interface)

Easyexcel export case (only you can't think of it)

docker mysql

Image processing: Generation 3 × Window of 3
![[STM32] basic knowledge of serial communication](/img/0f/7cc59fea9b1edf721c9d06b419896a.png)
[STM32] basic knowledge of serial communication

OSI open system interconnection model and tcp/ip model

kubernetes 部署 dashboard(可视化界面)

C language database: detailed description. Use the student management system to understand the operation of the database, which is simple and easy to understand.

The flare project celery uses the pits encountered in redis sentinel
随机推荐
1000个Okaleido Tiger首发上线Binance NFT,引发抢购热潮
Linx link, first level directory, redirection, CP and MV
Small farmers also have big goals in the test, and the latest big bat interview summary (constantly updating...)
ACL——net
How to solve cnpm stuck during execution?
freemarker
SkyWalking分布式系统应用程序性能监控工具-上
[QNX hypervisor 2.2 user manual]9 VM configuration reference
Chapter 1 water test --*offer
Memory forensics nssctf otterctf 2018 (replay)
Client does not support authentication protocol requested by server; consider upgrading MySQL client
数仓搭建——ODS层
Linkerd service grid survey notes
The flare project celery uses the pits encountered in redis sentinel
Image processing 1:rgb888_ YCbCr444
High voltage technology test questions and answers
Focus on microservices
[freeswitch development practice] column introduction
黑马程序员-接口测试-四天学习接口测试-第四天-Postman读取外部数据文件,读取数据文件数据,iHRM项目实战,员工管理模块,添加员工,批量运行测试用例,生成测试报告,
C language database: detailed description. Use the student management system to understand the operation of the database, which is simple and easy to understand.