C 预处理器
C 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。
指令 | 描述 |
---|---|
#define | 定义宏 |
#include | 包含一个源代码文件 |
#undef | 取消已定义的宏 |
#ifdef | 如果宏已经定义,则返回真 |
#ifndef | 如果宏没有定义,则返回真 |
#if | 如果给定条件为真,则编译下面代码 |
#else | #if 的替代方案 |
#elif | 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码 |
#endif | 结束一个 #if……#else 条件编译块 |
#error | 当遇到标准错误时,输出错误消息 |
#pragma | 使用标准化方法,向编译器发布特殊的命令到编译器中 |
1.取消已定义宏
demo.h文件代码如下
#ifndef __DEMO_H_
#define __DEMO_H_
#define PAI 3.14
#endif // __DEMO_H_
#include <stdio.h>
#include "demo.h"
#undef PAI
#define PAI 33.14
int main()
{
printf("PAI = %G\n", PAI);
}
2.使用#ifdef来调试
#ifdef DEBUG
#endif // DEBUG
如果定义了 DEBUG,则执行处理语句。在编译时,如果您向 gcc 编译器传递了 -DDEBUG 开关量,这个指令就非常有用。它定义了 DEBUG,您可以在编译期间随时开启或关闭调试。
常用预定义宏
宏 | 描述 |
---|---|
__DATE__ | 当前日期,一个以 “MMM DD YYYY” 格式表示的字符常量。 |
__TIME__ | 当前时间,一个以 “HH:MM:SS” 格式表示的字符常量。 |
__FILE__ | 这会包含当前文件名,一个字符串常量。 |
__LINE__ | 这会包含当前行号,一个十进制常量。 |
预处理器运算符
1.宏延续运算符
\
一个宏通常写在一个单行上。但是如果宏太长,一个单行容纳不下,则使用宏延续运算符\
#include <stdio.h>
#define PAI \
3.1415926
int main()
{
printf("%.8f\n", PAI);
}
2.字符串常量化运算符#
在宏定义中,当需要把一个宏的参数转换为字符串常量时,则使用字符串常量化运算符#
。在宏中使用的该运算符有一个特定的参数或参数列表。就是把宏的参数变成字符串。
#include <stdio.h>
#define PAI 3.1415926
//字符串常量化
#define CONVERT_TO_STR1(arg) "字符串常量化:" #arg
//字符串常量化
#define CONVERT_TO_STR2(arg) CONVERT_TO_STR1(arg)
int main()
{
printf("%s\n", CONVERT_TO_STR1(ABC));
printf("%s\n", CONVERT_TO_STR1(PAI));
printf("%s\n", CONVERT_TO_STR2(PAI));
}
这里有几点需要提一下。
1.宏定义中,当有多个字符串需要连接时,以空格来隔开每一个字符串即可。
2.当需要把一个宏字符串常量化时,需要按照先定义一个宏函数1,然后再定义一个宏函数2,然后宏函数2调用宏函数1即可,例如CONVERT_TO_STR2
调用CONVERT_TO_STR1
3.标记粘贴运算符##
宏定义内的标记粘贴运算符(##)会合并两个参数。它允许在宏定义中两个独立的标记被合并为一个标记。
#include <stdio.h>
#define PRINTF1(arg) printf("var" #arg " = %d\n" , var##arg)
int main()
{
int var1 = 20;
PRINTF1(1);
}
参数化的宏
使用注意点
用宏定义时,含参数时,参数本身要加(),此外,对参数的操作整体也要加()。
#define MAX(a,b) ((a)>(b)?(a):(b))
使用宏函数的时候不要使用++
/--
运算符
#include <stdio.h>
#define MIN(A,B) ((A)<(B)?(A):(B))
int main()
{
char *p="ghi";
char a;
a=MIN(*p++,'f');//不要使用自增/自减运算符
printf("%c\n",a);
}
另,宏定义实现指定大小的交换:
#define SWAP(a, b, size) \
unsigned int __size = (size); \
char *__a = (a), *__b = (b); \
do \
{ \
char __tmp = *__a; \
*__a++ = *__b; \
*__b++ = __tmp; \
} while (--__size > 0);
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!