当前位置:网站首页>Compilation (preprocessing) of C language program -- Part 2
Compilation (preprocessing) of C language program -- Part 2
2022-07-21 12:07:00 【Long Zhaowan】
3. Next chapter #define
3.2.2 #define Defining macro
#define The mechanism includes a provision , Allow to put Replace parameters with text , This implementation is often referred to as a macro or definition macro .
Then we can write Similar to function , however It cannot be confused with the concept of function . Here is how macros are declared :
#define name(parament-list) stuff
Here's the thing to watch out for : Of the parameter list The left parenthesis must be the same as name Next door neighbor .
Now let's look at the usage :
#include <stdio.h> #define ADD(X) X+X int main() { printf("%d\n", ADD(3)); return 0; }
This is a very simple macro for calculating addition , We must make clear the difference between macros and functions . Functions pass parameters , But what the macro does is replace the text . We can add comments to the code for easy reading .
#include <stdio.h> #define ADD(X) X+X // that X I was 3 replace ---> ADD(3) 3+3 int main() { printf("%d\n", ADD(3));// Passed a 3 return 0; }
Since all that is done is text substitution , Then there will be the following ambiguity :
#include <stdio.h> #define SUB(X) X*X int main() { printf("%d\n", SUB(3+2)); return 0; }
According to our intuition , The calculation completed by the macro should be (3+2)*(3+2) = 25 . In fact, macros only complete text replacement , and Do not operate on parameter expressions .
The calculation process of the above answer is 3+2*3+2 = 11 .
So since we want to avoid ambiguity , You need to add brackets manually .
#include <stdio.h> #define SUB(X) ((X)*(X)) int main() { printf("%d\n", SUB(3+2)); return 0; }
It's not just about adding parentheses to text replacement objects , You must also add parentheses to the macro expression , Form a whole . This can avoid many problems , Let's not list one by one .
3.2.3 #define Replacement rules
Extend... In a program #define When defining symbols and macros , The following steps need to be involved .
- When calling a macro , First, check the parameters , See if it contains any information from #define Defined symbols . If by , They were first replaced .
- 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 there is , Just repeat the above steps .
It should be noted that :
- Macro parameters and #define Other... Can appear in the definition #define Defined symbols . But for macros , No recursion . in other words , When using macros , You can call other macros , But never call yourself .
- When the preprocessor searches #define When defining symbols , The contents of string constants are not searched . We use code to explain this :
#include <stdio.h> #define TEST(X) ((X)+(X)) int main() { char* str = "TEST";// String constant duplicates macro name , But the preprocessor does not look printf("%d", TEST(3)); return 0; }
3.2.4 # Use
First, let's look at the following printf Unconventional usage of :
#include <stdio.h> int main() { printf("hello " "world" "\n"); return 0; }
This code will output normally hello world Of .
So what exactly do we want to express ?
For example, we write a function :
#include <stdio.h> void print(int n) { printf("a = %d", n); } int main() { int a = 3; print(a); return 0; }
This code will output a = 3, But we put a The variable name of is changed to b , We want this program to output b = 3, Is obviously inconvenient , Because we need to modify it manually .
#include <stdio.h> void print(int n) { printf("a = %d", n); } int main() { int b = 3; print(b); return 0; }
But in macros , You can use # and printf Cooperate with each other to achieve this effect .
#include <stdio.h> // # The function of is to change parameters into strings #define PRINT(value,format) printf("the value of " #value " is " format "\n",value) // == printf("the value of " "a" " is " " %d " "\n",value ) int main() { int a = 3; PRINT(a, "%d"); return 0; }
3.2.5 Macro parameters with side effects
When macro parameters appear more than once in the macro definition , If the parameter has side effects , Then there may be danger when using this macro , Lead to unpredictable consequences . The side effect is the permanent effect of expression evaluation . Is like saying :
x+1;// Of this expression x The value remains the same , No side effects x++;// This expression x=x+1; x The value of will change , With side effects
Let's see what happens when using macros with side-effect parameters :
#include <stdio.h> #define MAX(a,b) ((a)>(b)?(a):(b)) int main() { int x = 5; int y = 8; int z = MAX(x++, y++); printf("x=%d y=%d z=%d\n", x, y, z); return 0; }
Let's analyze :
3.2.6 Macro and function comparison
Macros are often used to perform simple calculations . Then why not use functions to complete simple calculations ?
There are two reasons :
- The code used to call the function and return from the function may take more time than it actually takes to perform this small computation . So macros are better than functions in terms of program size and speed .
- More importantly, the parameters of the function must be declared as specific types . So functions can only be used on expressions of the right type . But macro parameters don't need to declare types .
Of course , Since there are functions and macros , It shows that both are indispensable , Macro has the following disadvantages :
- Every time you use a macro , A copy of the code defined by the macro is inserted into the program , Unless the macro is short , Otherwise, the length of the program may be greatly increased .
- Macros cannot be debugged .
- Macro is type independent , It's not rigorous enough .
- Macros can cause operator priority problems , Cause the program to be error prone .
3.2.7 Naming conventions
Generally speaking, the usage syntax of function macros is very similar . So language itself can't help us distinguish the two . But we have a habit : Macro names are all capitalized , Function names are all lowercase . I have to mention here offsetof This macro , At first glance, it looks like a function , In fact, it is a macro . Its function is to find out the structural members relative to 0 Offset of address . If you forget the structure memory alignment , You can review the following . ad locum , Let's simulate the following offsetof macro .
#include <stdio.h> #define OFFSETOF(type,member) ((int)(&(((type*)0)->member))) struct S { char a; int b; char c; }; int main() { printf("%d\n", OFFSETOF(struct S, a)); printf("%d\n", OFFSETOF(struct S, b)); printf("%d\n", OFFSETOF(struct S, c)); return 0; }
Let's split our implementation principle .
3.3 #undef
This instruction is used to remove a macro definition .
#include <stdio.h> #define OFFSETOF(type,member) ((int)(&(((type*)0)->member))) struct S { char a; int b; char c; }; int main() { #undef OFFSETOF // take OFFSETOF Undefine printf("%d\n", OFFSETOF(struct S, a)); printf("%d\n", OFFSETOF(struct S, b)); printf("%d\n", OFFSETOF(struct S, c)); return 0; }
3.4 File contains
We need to know ,#include This instruction enables the header file to be compiled at compile time .
We also know that there are two ways to include header files :
#include <stdio.h> #include "stdio.h"
What is the difference between these two inclusion methods ?
- For the first one , Search the header file directly to the standard path , That is, go directly to the header file library brought by the compiler to find .
- For the second , The header file to be searched will first be searched under the project directory , If you can't find it , Then go to the standard path to find .
in other words , Library files can be used "" contain , But it will be inefficient . So there is an unwritten rule when using header files : When including library files , Use <> , When you include your own header file , Use "" .
边栏推荐
猜你喜欢
Formatage hbuilderx sans nouvelle ligne (importation)
技术分享 | 实战详解接口测试请求方式Get、post
KDD cup 2022 Baidu - List
Could not resolve all dependencies for configuration的解决方案
Simulated exhaustive 731 My schedule II
chrome插件开发入门实战——CSDN免登陆拷贝、免关注查看
使用Room所遇到的 Execution failed for task ‘:app:kaptDebugKotlin‘
专业的人做专业的事 GBASE参编数据库发展研究报告(2022年)、入选全球数据库产业图谱
sqlilabs less-26~26a
【excel】SUMIF合并单元格
随机推荐
BCG 使用之CBCGPColorDialog控件
你必须知道的4种 Redis 集群方案及优缺点对比
技术分享 | 实战详解接口测试请求方式Get、post
截取指定字符前后字符串
Mysql:Error Code 1235,This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME
HTB-Bashed
Singleton mode of creation mode
KDD cup 2022 Baidu - List
2021-09-16
什么是组合(Composition),有什么作用
模拟穷举 731. 我的日程安排表 II
龙蜥社区发布首个 Anolis OS 安全指南 为用户业务系统保驾护航
chrome插件开发入门实战——CSDN免登陆拷贝、免关注查看
"Fundamentals of program design" Chapter 10 function and program structure 7-2 Hanoi Tower problem (20 points)
支持向量机学习笔记(2)参数比较与人脸识别项目
Why is kubernetes a new application server
jeecg中j-vxe-table和j-popup组件的修改使用
sqlilabs less-27
Intercept the string before and after the specified character
HTB-Lame