C语言学习笔记_C语言宏定义与预处理

C语言学习笔记_C语言宏定义与预处理

由源码到可执行程序的过程

  1. 源码;
  2. 预处理过的.i源文件
  3. 汇编文件.s
  4. 目标文件.o
  5. elf可执行程序

条件编译

// 定义XXX
#define XXX

// 这种方式直接判定XXX是否被定义
#ifdef XXX
#else
#endif

// 这种方式判断条件是否为真
#if (1)
#else
#endif

宏定义

宏定义在编译器的预处理阶段会被直接替换;

替换的过程是递归的,如下:

#define N 10
#define M N

// 相当于int a[10];
int a[M];

当宏定义带参数的时候,擅用括号,避免替换的时候出现歧义,如获取最大值的宏:

#define MAX(a, b)	((a) > (b) ? (a) : (b))

int max(int a, int b) {
    return a>b?a:b;
}

int a = 1, b = 2;
int max = MAX(a*3, b);

这里例子可能举得不是很好,但是在某些时候不加括号会使得替换后引起歧义,导致出错;

带参宏和带参函数有如下差别:

  1. 宏定义原地展开,因此没有调用开销;而函数是跳转执行在返回;
  2. 宏定义不会检查参数的类型,返回值也不会附带类型,而函数有明确的参数类型和返回值类型;当调用函数时编译器会做参数的静态类型检查;

另外一个例子,利用宏定义得到一年有多少秒:

#define SER_PER_YEAR	(365*24*60*60UL)

注意:

在程序中的数字默认为int类型,而秒数正好超过了int的范围;

所以在数字后面加上UL使得数组变成无符号long;

另外一个例子,利用条件宏设置debug

// 定义DEBUG
#define DEBUG

// 使用undef消除对DEBUG的定义
#undef DEBUG

#ifdef DEBUG
#define debug(x) printf(x)
#else
#define debug(x)
#endif


debug("hello world.\n");

通过定义DEBUG,使得debug可以用于打印信息,如果不需要了可以注释DEBUG的定义,或者使用undef,使得消除调试信息更方便。

使用undef时,前面若没有定义过,将会无视此语句;

内联函数

在宏定义中讲到,带参宏和函数的区别是:带参宏开销小但是不做类型检查,函数有调用开销但是会做类型检查;

而内敛函数具有上述两者的优点,其没有调用开销且会做类型检查,只需要在函数前加inline

inline void printInfo() {
	printf("hello world.\n");
}
posted @ 2020-07-13 22:44  樱花小猪  阅读(280)  评论(0编辑  收藏  举报