24.预处理详解

简介: 24.预处理详解

1.预定义符号

使用

printf("file:%s line:%d\n",__FILE__,__LINE__);

2.#define 定义常量

基本语法:

~1.for(;;)会形成死循环

~2.第一个最好不要用,第一个case前不应该有break

思考:#define后面要不要加上;

    不建议,因为会形成两条句子,造成语法错误

3.#define定义宏

允许把参数替换到文本中,这种实现叫做定义宏

声明方式:

#define  SQUARE(x)  x*x
int a=5;
printf("%d\n",SQUARE(a+1));

以上这段代码,将a+1这个参数以文本的形式替换了进去,变为了a+1*a+1,理想状态是打印36,但会发现实际打出来的是11,替换产生的表达式并没有按照预想的次序进行求值

所以,宏定义定义进行单纯的文本替换,不要吝啬括号

将代码更改为

#define  SQUARE(x)  (x)*(x)

这样就可以达到预期的效果啦

这里还有一个宏定义:

解决方法是:在宏定义表达式两边加上一对括号,变为:

#define DOUBLE(x)  ((x)+(x))  

所以用于数值表达式进行求值的宏定义,都应该用这种方式加上括号

4.带有副作用的宏参数

5.宏替换的规则

例如:

max(m,3)可以,但是max(max())这种形式就不可以

6.宏与函数的对比

优势:

~1.宏比函数在程序的规模和速度方面更胜一筹,例如见预处理完了的.i文件

函数              代码行数
1.调用函数   11 1.执行    7~8行
2.执行运算    7~8
3.函数返回     6

~2.宏的参数是类型无关的

劣势:

对比主要体现在:

代码长度,执行速度,操作符优先级,带有副作用的参数,参数类型,调试,递归等

7.#和##

1.#运算符

如果想将一个宏的参数转化为字符串字面量,需要将其字符串化,在打印时经常用到,如

PRINT(a) 运行代码打印出:

the value of a is 10

2.##运算符

例如:GENERIC(int)  //替换到宏体内后float##_max 生成了新的符号 float_max做函数名

8.命名约定

宏名全部大写,函数名不要全部大写

#undef 用于移除一个宏定义,如果现存一个名字需要被重新定义,那么它的旧名字首先要被移除

9.命令行定义

允许在命令行中定义符号,在同一源文件要编译出一个程序的不同版本的时候会用到

10.条件编译

在对代码进行调试时,会用到,记得结尾要加 #endif

11.文件的包含

头文件:#include "name"

库文件: #include<name.h>

 也可以用“ ”,但是这样查找的效率就低一些,要先遍历完头文件未找到,再来到库文件找

嵌套文件:容易存在头文件被重复包含

那么如何解决被重复引用的问题————条件编译

每个头文件这样写

或者 #pragma  once

这样就可以避免头文件的重复引入啦


相关文章
|
6月前
|
编译器 C++
C 预处理器
C 预处理器。
84 10
|
1月前
|
编译器 Linux C语言
|
6月前
|
编译器 C语言
预处理深入
预处理深入
36 0
预处理深入
|
6月前
|
编译器 C语言
c预处理器
c预处理器
39 0
|
6月前
|
Linux C语言 Windows
C预处理分析
C预处理分析
40 2
|
6月前
|
安全 C语言
程序预处理:全解版-1
程序预处理:全解版
38 0
|
6月前
|
编译器 C语言
程序预处理:全解版-2
程序预处理:全解版
37 0
|
6月前
|
编译器 C++
c++预处理器
c++预处理器
38 0
|
12月前
|
安全 编译器 C语言
详解预处理(1)
详解预处理(1)
78 1
|
12月前
|
编译器 Linux C语言
详解预处理(2)
详解预处理(2)
75 0