C与指针-第十四章--预处理器

预处理器是在真正的编译开始之前由编译器调用的独立程序。预处理器可以删除注释、包含其他文件以及执行宏(宏macro是一段重复文字的简短描写)替代。预处理器可由语言(如C,PHP要求或以后作为提供额外功能(诸如为FORTRAN提供Ratfor预处理器)的附加软件。

预定义宏

ANSI C定义了一些宏。虽然每一个可以供您使用的编程,预定义宏不应该被直接修改。

符号 例子 含义
DATE “Jun 18 2016” 文件被编译的时间
TIME “15:47:03” 文件被编译的时间
FILE “test.c” 进行编译的源文件名
LINE “8” 文件当前的行号
STDC “1” 如果编译器遵循ANSI C,其值就为1,否则未定义

例子:

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main()
{
printf("File :%s\n", __FILE__ );
printf("Date :%s\n", __DATE__ );
printf("Time :%s\n", __TIME__ );
printf("Line :%d\n", __LINE__ );
printf("ANSI :%d\n", __STDC__ );
}

输出:
File :test.c
Date :Jun 18 2016
Time :15:47:03
Line :8
ANSI :1

预处理常量 define:

预处理器指令从#开始,到最后第一个换行符为止。如果在结尾出现反斜杠,则定义会自动延续到下一行。

1
2
3
4
5
6
7
8
/*define定义一个常量MAX_VALUE*/
#define MAX_VALUE 10
/*define结尾出现反斜杠,定义自动延续到下一行*/
#define PARAGRAPH “This is the first example\
of define "

printf(“max value is %d\n”,MAX_VALUE);
printf(“paragraph is %s\n”,PARAGRAPH);

每个define行有三部分组成。

  • 第一部分为#define本身;
  • 第二部分为所选择的缩略语,成为宏,宏的名字中不允许有空格,我们约定使用大写表示。
    *第三部分为宏替换的文本,成为宏展开。如果没有替换文本,我们成为一个基本宏定义。

宏判断:

如果我们想一些段落代码,只在部分宏有定义的情况下才只用,我们这里会用到宏判断。
格式:

1
2
3
4
5
#ifdef XXX
...
#else
...
#endif

例:

1
2
3
4
5
6
7
8
9
10
11
12
#define PROJECT_TEST

int main(void)
{

#ifdef PROJECT_TEST
printf(“marco PROJECT_TEST is defined\n”);
#else
printf(“marco PROJECT_TEST not defined\n”);

#endif
return 0;
}

如果我们在工程中定义了PROJECT_TEST这个宏,则打印第一段,否则打印第二段。

宏函数:

宏函数,即用宏的方式来实现函数。
宏函数末尾不能带分号做结尾。
宏函数中的参数都需要用括号扩起来。

例如:

1
2
3
4
5
#define SEQUERE(a) a*a
int seq_value;
int a = 4;
seq_value = SEQUERE(a);
printf(“seq_value = %d\n”,seq_value);

输出:16

但是这种写法有个问题,如果我们传入的a为 a+1时,就会发生问题。

1
2
3
4
int seq_value;
int a = 4;
seq_value = SEQUERE(a+1);
printf(“seq_value = %d\n”,seq_value);

输出: 9
输出的内容为9,而不是我们期望的25.
我们简化一下这个程序

SEQUERE(a) aa
变为a+1
a+1
a为4,所以结果为4+1*4+1 = 9.

为了避免这种情况,我们在宏函数中的每个参数都需要用小括号()括起来。
即为#define SEQUERE(a) (a)*(a)

Tianger Ge wechat
如果您喜欢这篇文章,欢迎扫一扫我的微信公众号!