本篇文章同样适用于C++

概述

define预处理器,通常可以预定义常量,如经典预定义之圆周率

1
#define PI 3.1415926

PI 为常量名称,3.1415926 为常量内容

什么是预定义

顾名思义,即为预先定义。在C语言编译运行之前的预处理阶段会开始处理该预定义常量,听起来有些拗口,请看以下例子:

代码编写阶段:

1
2
3
4
5
#include <stdio.h> //C标头
#define RECT (20*20) //定义一个RECT常量,其值为400
void main(){
printf(RECT);
}

进入预处理阶段(未进入编译运行阶段):

1
2
3
4
5
#include <stdio.h> //C标头
#define RECT (20*20) //定义一个RECT常量,其值为400
void main(){
printf(400);
}

可以看到在预处理阶段,预处理器会自动运算20*20的结果并将其RECT常量自动转换为运算值。

注意:在define中若有数学运算必须使用()括起

像这种写法就是错误的:

1
2
#define RECT 20*20 //错误
#define RECT (20*20) //正确

const修饰符与define预处理器的区别

1、编译器处理方式不同

  • define 宏是在预处理阶段展开。
  • const 常量是编译运行阶段使用。

2、类型和安全检查不同

  • define 宏没有类型,不做任何类型检查,仅仅是展开。
  • const 常量有具体的类型,在编译阶段会执行类型检查。

3、内存分配不同

  • define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。
  • const常量会在内存中分配(可以是堆中也可以是栈中)。

4、性能开销不同

虽然作用甚微,但还是有的。

在定义常量的时候不会立刻分配内存,而是加载到符号表里,需要时才分配内存,此时会有唯一的一个内存地址,如果需要调用该常量则只需要访问该内存地址就可以获取常量的值。

而define若在编译期间进行宏替换,会分配内存,但在编译前进行宏替换则不会分配内存。

define的常量有多少次调用就会有多少次分配,而const不一样。

作用域

其常量作用域为整个代码,与全局变量一样。

定义函数

define还可以用来定义函数,可以像这样定义一个简单的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
#define MAX(a,b) (a<b)?b:a //求最大值函数

int main(){
printf("%d", MAX(10,20))
return 0;
}
//输出结果为20

//如果不使用define定义这类简单的函数,代码量会变多:
int max(int a, int b){
return a<b?b:a;
}

通常并不建议频繁使用define定义函数,使用define定义的函数通常是代码量较少且需要多次频繁调用的函数,它与内联函数类似,在程序编译运行之前会将函数代码块直接拷贝到调用的地方,能略微提升性能

但这并不代表你可以乱用,如果乱使用define定义函数会导致代码编译时间长,代码可读性下降等,由于它是直接将对应的代码展开拷贝的特性,在某些情况下可能会产生意想不到的后果。(不然干脆函数定义全用define得了