当前位置:网站首页>C语言 预处理详解
C语言 预处理详解
2022-07-26 00:06:00 【东区东区!】
目录
一、预定义符号
int main()
{
int i = 0;
for (i = 0; i < 5; i++)
{
printf("file:%s line:%d date:%s time:%s i = %d\n", __FILE__, __LINE__, __DATE__, __TIME__,i);
}
return 0;
}打印结果如下

二、#defifine
1.#defifine 定义标识符
语法:#define name stuff //后面一般不加封号
使用一般如下,看到定义的符号就是替换
#define num 100
#define STR "abcd"
int main()
{
int a = num;
char* str = STR;
return 0;
}其他情况
#define MAX 1000
#define reg register //为 register这个关键字,创建一个简短的名字
#define do_forever for(;;) //用更形象的符号来替换一种实现
#define CASE break;case //在写case语句的时候自动把 break写上。
// 如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。
#define DEBUG_PRINT printf("file:%s\tline:%d\t \
date:%s\ttime:%s\n" ,\
__FILE__,__LINE__ , \
__DATE__,__TIME__ )2.#defifine 定义宏
#define name( parament-list ) stuff #define MAX(x,y) (x>y?x:y)
int main()
{
int a = 20;
int b = 30;
int c = MAX(a, b);
printf("%d\n", c);
return 0;
}注意:写宏的时候不能吝啬括号
例一:
#define SQUARE( x ) x * x这个宏接收一个参数 x . 如果在上述声明之后,你把
SQUARE( 5 );置于程序中,预处理器就会用 5 * 5 表达式替换上面的表达式
int a = 5;
printf("%d\n" ,SQUARE( a + 1) )#define SQUARE(x) (x) * (x)例二:
#define DOUBLE(x) (x) + (x)这个也会由问题
int a = 5;
printf("%d\n" ,10 * DOUBLE(a));printf ("%d\n",10 * (5) + (5));#define DOUBLE( x) ( ( x ) + ( x ) )3.#defifine 替换规则
三、#和##
1.#作用
把参数插入到字符串
//宏解决
#define PRINT(N) printf("the value of " #N" is %d\n", N)
int main()
{
int a = 10;
PRINT(a);
int b = 20;
PRINT(b);
return 0;
}再比如
int i = 10;
#define PRINT(FORMAT, VALUE)\
printf("the value of " #VALUE "is "FORMAT "\n", VALUE);
...
PRINT("%d", i+3);/2.##的作用
#define CAT(name, num) name##num
int main()
{
int class105 = 105;
printf("%d\n", CAT(class, 105));
return 0;
}打印结果为105.意思就是,传入的为class和105 ,##可以把他们合并为已经定义的class105,结果为105
四、宏和函数对比
1.总对比表
属 性 | #defifine定义宏 | 函数 |
代 码 长 度 | 每次使用时,宏代码都会被插入到程序中。除了非常小的宏 之外,程序的长度会大幅度增长 | 函数代码只出现于一个地方;每次使 用这个函数时,都调用那个地方的同 一份代码 |
执 行 速 度 | 更快 | 存在函数的调用和返回的额外开销, 所以相对慢一些 |
操 作 符 优 先 级 | 宏参数的求值是在所有周围表达式的上下文环境里,除非加 上括号,否则邻近操作符的优先级可能会产生不可预料的后 果,所以建议宏在书写的时候多些括号 | 函数参数只在函数调用的时候求值一 次,它的结果值传递给函数。表达式 的求值结果更容易预测 |
带 有 副 作 用 的 参 数 | 参数可能被替换到宏体中的多个位置,所以带有副作用的参 数求值可能会产生不可预料的结果。 | 函数参数只在传参的时候求值一次, 结果更容易控制 |
参 数 类 型 | 宏的参数与类型无关,只要对参数的操作是合法的,它就可以使用于任何参数类型。 | 函数的参数是与类型有关的,如果参 数的类型不同,就需要不同的函数, 即使他们执行的任务是不同的 |
调 试 | 宏是不方便调试的 | 函数是可以逐语句调试的 |
递 归 | 宏是不能递归的 | 函数是可以递归的 |
宏的缺点:
1. 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序的长度。
2. 宏是没法调试的。
2.命名约定
3.#undef
#undef NAME
//如果现存的一个名字需要被重新定义,那么它的旧名字首先要被移除。五、条件编译
边栏推荐
猜你喜欢

二叉树——110. 平衡二叉树

用了MQ消息中间件后,我开始后悔了...

NVIDIA可编程推理加速器TensorRT学习笔记(三)——加速推理

The items of listview will be displayed completely after expansion

Android solves the risk of database injection vulnerability

本轮牛市还能持续多久?|疑问解答 2021-05-11

Binary tree - 112. Path sum

Old laptop becomes server (laptop + intranet penetration)

Stack and queue - 239. Sliding window maximum

Binary tree -- 104. Maximum depth of binary tree
随机推荐
Yolov4 tiny network structure
Binary tree - 530. Minimum absolute difference of binary search tree
Stack and queue - 347. Top k high frequency elements
Leetcode107-二叉树的层序遍历II详解
Nest.js 用了 Express 但也没完全用
Js理解之路:Js常见的6中继承方式
Backtracking - 17. Letter combinations of phone numbers
关于拼多多根据关键词取商品列表 API 的使用说明
没错,请求DNS服务器还可以使用UDP协议
What does it mean that the web server stops responding?
Binary tree 101. Symmetric binary tree
Observer model of behavioral model
How to use yolov5 as an intelligent transportation system for red light running monitoring (1)
如何用120行代码,实现一个交互完整的拖拽上传组件?
栈与队列——347. 前 K 个高频元素
MPLS实验
Are you still using your browser's own bookmarks? This bookmark plugin is awesome
复盘:推荐系统—— 负采样策略
Leetcode200 - find detailed explanation of the number of islands
Binary tree - 112. Path sum