第八章——编译预处理

8.1 宏定义

梳理一个项目的构成
针对一个.cpp文件进行预处理 编译 汇编
链接成为.obj文件
针对一个.cpp文件进行预处理 编译 汇编
针对一个.cpp文件进行预处理 编译 汇编
可执行文件.exe

在预处理过程中,是指对于一些特殊的代码进行预先的处理,比如 # 开头的 宏定义、文件包含、条件编译

不带参数的宏定义

说明:

  • 严格来说,宏定义并不是 C 语言语句,宏定义的作用是用一个指定的宏名来代表一段内容,这样能够使得代码修改变得就极为便利
#define 宏名 被替换的内容
#define PI 3.1415926  // 由于宏定义不是C语言的语句,所以宏定义是没有分号的
// 注意,如果加了分号,那么分号也是算在被替换的内容之中
  • 宏定义不能跨文件使用,一般工程中可以将宏定义放到一个公共文件中,然后只要在源文件中包含这个头文件就好
  • 宏定义的作用范围是整个源文件,如果想终止其作用范围,可以用 #undef 命令来终止,表示这行以后,宏的定义无效
  • 在定义宏时,还可以引用已定义的宏,可以层层替换
#define PI 3.14
#define DPI 2 * PI
#define DPICPI DPI * PI // 最终,DPICPI 是 2 * 3.14 * 3.14
带参数的宏定义

前面讲的不带参数的宏定义知识进行简单的内容替换,而带参数的宏定义则可以进行参数替换

#define 宏名(参数表) 被替换的内容  // 注意,这里宏名和参数表之间一定不能有空格,不然就成了不带参数的宏定义

// 范例
#define S(a,b) a * b
int Area = S(3,2); // 输出Area: 6

说明:

  • 考虑运算符的优先级
#define S(a,b) a + b

int a = 3 * S(2,5); // 等价于 3 * 2 + 5 ,这样的结果显然不是我们想要的,因此,可以将宏定义改为 #define S(a,b) (a + b)
  • 从上面的例子也可以看出,宏定义展开的话,是不进行运算的,比如上面的 2 + 5
  • 宏定义经过预处理后,其不占内存,而且,宏展开是在编译阶段(宏展开是指有参数的宏定义),因此也不占运行时间

文件包含和条件编译

文件包含

我们可以用#include 将一个任何其他文件的全部内容包含到当前的文件中,但是一般来说,还是将 .h 类型(头文件)文件包含进来。这个命令的本质是将另一个文件的全部内容搬到命令当前行

条件编译

有时我们希望,只要满足一定的条件,那么就对其中的一部分代码进行编译,而不满足的话,就对编译另一段代码。最典型是一段代码既要在 window 下编译运行,也要在 Linux 下编译运行,这时候一般会使用条件编译、

  1. 形式 1
# ifdef 标识符 // 如果宏定义了这个标识符,则执行程序段 1
	程序段 1(一堆代码)
# else // 否则执行程序段 2
    程序段 2(一堆代码)
# endif
        
范例:
# define DEBUG 1

# ifdef DEBUG
        printf("输入一些变量信息作为调试信息\n",);
# endif

// 当我们不想 debug 的时候,只要将 DEBUG 的宏定义注释就好
  1. 形式 2
# ifndef 标识符 // 如果没有宏定义这个标识符,就执行程序段
	程序段 1
# else
    程序段 2 // 定义了则执行程序段 2
# endif
  1. 形式 3
# if 表达式 // 当表达式为真时,则执行程序段 1
	程序段 1
# else // 否则执行程序段 2·
    程序段 2
# endif

作用:

  • 条件编译可以减少目标程序长度
  • 在项目开发中,为了增加程序在各平台上的可移植性,往往采用条件编译,这样的话,就可以在不修改源代码的条件下编译通过
# if _WIN32 // windows 平台
	// 这里有一些Windows专用函数
	print("当前是Windows平台\n");
# elif __Linux__ // Linux 平台
	// 这里有一些Linux专用函数
# else
	// 其他平台
# endif

猜你喜欢

转载自blog.csdn.net/weixin_57095511/article/details/119920138
今日推荐