当前位置:网站首页>[C language] Preprocessing operation
[C language] Preprocessing operation
2022-07-31 03:10:00 【Ahao_te】
在编译一个CLanguage involves many steps.The first step is the preprocessing stage.
1、预处理详解
1.1、预定义符号
The table below summarizes the reasons预处理器定义的符号.Their values are either string constants,Or a decimal numeric constant.__ FILE __ 和 __ LINE __ Used to view the file's disk address and source file code line number, respectively,__ DATE __ 和 __ TIME represent the date and time, respectively, STDC __ Identify if the compiler followsANSI C.
具体展示:
#include<stdio.h>
int main()
{
int i = 0;
FILE* pf = fopen("log.txt", "w");
if (pf == NULL)
{
perror("fopen");
return -1;
}
for (i = 0; i < 10; i++)
{
fprintf(pf, "file:%s line=%d date:%s time:%s i=%d\n", __FILE__, __LINE__, __DATE__, __TIME__, i);
}
fclose(pf);
pf = NULL;
return 0;
}

1.2、#define
1.2.1 #define 定义标识符
#define name stuff
比如
#define MAX 1000
//如果是 #define MAX 1000;
//max = 1000;; 不太合适
if(condition)
max = MAX;
else
max = 0;
1.2.2 #define 定义宏
#define The mechanism has a rule,Run replaces the arguments into the text,This implementation is called a macro or definition macro.
下面是宏的声明方式:
#define name( parament-list ) stuff
其中parament-list is a comma-separated list of symbols,它们可能出现在stuff中.
注意:
参数列表的左括号必须与name紧贴.
如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分.
See below for macro substitution
比如有一个
#define SQUARE( x ) x*x
SQUARE(5);将会等于55,那么如果是SQUARE(5 + 1),就会等于5 + 1 * 5 +1.
This reminds us more clearly,when defining a macro,It is best to leave out the parentheses.
比如x * x写成 ((x)(x)),This allows us to get the expected results more accurately.
1.2.3 #define 替换规则
- 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号.如果是,它们首先被替换.
- 替换文本随后被插入到程序中原来文本的位置.对于宏,参数名被他们的值所替换.
- Finally see if there are more#define定义的符号.Repeat if so1,2步骤.
注意:
- 宏参数和#define 定义中可以出现其它#define 定义的符号.但是对于宏,不能出现递归.
- 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索.
1.2.4 #和##
如何把参数插入到字符串中?
char* p ="hello ""world\n";
printf("hello," world\n);
printf("%s",p);
这里输出的是不是
hello world?
是,我们发现字符串是有自动连接的特点的.
When a string is used as a macro parameter, I want to put it into a string as a string.
用# ,Turns a macro argument into a string for .
That is the case below
将i+3作为参数传给VALUE,并且通过#Puts the original content of the parameter into a string as a string.
int i = 10;
#define PRINT(FORMAT, VALUE)\ printf("the value of " #VALUE " is "FORMAT "\n", VALUE);
...
PRINT("%d", i+3); //产生什么效果?

##的作用
##The symbols on both sides can be combined into one symbol
注意:
这样的连接必须产生一个合法的标识符.否则结果就是未定义的.
#define CAT(str, Num) str##Num
int main()
{
char* str1 = "hello world";
printf("%s\n", CAT(str, 1)); //"hello world"
printf("%s\n", str1); //"hello world"
return 0;
}
1.2.4 with side effects宏参数
x+1; without 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);
输出结果:6,10,9.
1.2.4 宏和函数对比
Macros are usually used to perform simple operations.
For example, when you need some simple addition, subtraction, multiplication and division operations,The excellence of macros is more prominent.
因为:
- 宏比函数在程序的规模和速度方面更胜一筹
- 宏与类型无关
But macros also have drawbacks
- 每次使用宏的时候,The code defined by the macro needs to be inserted into the program.除非宏比较短,否则可能大幅度增加程序的长度.
- 宏是无法调试的.
- Macros are type-independent,所以不够严谨
- Macros can introduce priority issues,It is easy to make program errors.
1.2.4 命名约定
宏名全部大写
函数名不要全部大写
1.3 #undef
#undef NAME
用于移除一个宏定义
1.4 条件编译指令
When some debug code,删除可以,保留又碍事,所以我们可以选择性的编译.
比如:
#define __DEBUG__
int main()
{
int i = 0;
int arr[10] = {
0 };
for (i = 0; i < 10; i++)
{
arr[i] = i;
#ifdef __DEBUG__
printf("%d\n", arr[i]);
#endif //__DEBUG__
}
return 0;
}
There are other common conditional compilation directives:
#define M 6
int main()
{
#if M<5
printf("haha\n");
#elif M==5
printf("heihei\n");
#else
printf("hey!\n");
#endif
return 0;
}
ifndef == if not define
ifdef == if define
#define MAX 100
int main()
{
#ifndef MAX //#indef MAX
printf("max\n");
#endif
return 0;
}
1.5 实现OFFSETOF
宏定义offsetofIt is used to observe the offset address of the structure member.
offsetof(type, m_name)
比如
#include <stddef.h>
struct S
{
char c1;
int a;
short c2;
char c3;
};
int main()
{
struct S s = {
0 };
printf("%d\n", offsetof(struct S, c1));
printf("%d\n", offsetof(struct S, a));
printf("%d\n", offsetof(struct S, c2));
printf("%d\n", offsetof(struct S, c3));
}

从地址为0to access structure members,You can get the corresponding address and the equivalent offset.
struct S
{
char c1;
int a;
short c2;
char c3;
};
#define OFFSETOF(type,name) (int)&(((type*)0)->name)
int main()
{
struct S s = {
0 };
printf("%d %d %d %d",OFFSETOF(struct S, c1), OFFSETOF(struct S, a),
OFFSETOF(struct S, c2), OFFSETOF(struct S, c3));
return 0;
}
本章完
边栏推荐
- 8、统一处理异常(控制器通知@ControllerAdvice全局配置类、@ExceptionHandler统一处理异常)
- 4、敏感词过滤(前缀树)
- Point Cloud DBSCAN Clustering (MATLAB, not built-in function)
- Detailed explanation of TCP (1)
- 12 Disk related commands
- 2022 Nioke Multi-School League Game 4 Solution
- Unity3D Button mouse hover enter and mouse hover exit button events
- QML的使用
- try-catch中含return
- 注解用法含义
猜你喜欢

5. SAP ABAP OData 服务如何支持 $filter (过滤)操作

TCP详解(三)

JS function this context runtime syntax parentheses array IIFE timer delay self.backup context call apply

Detailed explanation of TCP (3)

【动态规划】连续子数组的最大和

10、Redis实现点赞(Set)和获取总点赞数

TCP详解(一)

什么是分布式锁?实现分布式锁的三种方式

接口测试关键技术

Recursive query single table - single table tree structure - (self-use)
随机推荐
Moxa NPort device flaw could expose critical infrastructure to devastating attack
10 Permission introduction
下载jar包的好地方
遗留系统的自动化策略
TCP详解(一)
16、热帖排行
学习DAVID数据库(1)
品牌广告投放平台的中台化应用与实践
加密公司向盗窃的黑客提供报价:保留一点,把剩下的归还
LeetCode中等题之分数加减运算
共模电感的仿真应用来了,满满的干货送给大家
【动态规划】连续子数组的最大和
CentOS7下mysql5.7.37的卸载【完美方案】
[Android] Room - Alternative to SQLite
The use of font compression artifact font-spider
点云DBSCAN聚类(MATLAB,非内置函数)
The simulation application of common mode inductance is here, full of dry goods for everyone
Atomic operation CAS
7、私信列表
Discourse Custom Header Links