关于预处理的“常识”
预处理并不是编译,也不是“预编译”。
预处理并不是每个语言都有的。
C/C++预处理仅仅是把源程序划分和整理成一个个的段(phase),并不进行编译。
预处理器在UNIX传统中通常缩写为PP,在自动构建脚本中C预处理器被缩写为CPP的宏指代。为了不造成歧义,C++(c-plus-plus) 经常并不是缩写为CPP,而改成CXX。
C语言预处理符号
ANSI C标准要求支持的预处理符号包括:
#define、#undef(宏定义), #include(文件包含), #if、#else、#elif、#endif、#ifdef、#ifndef(条件编译), #line(行控制), #error(错误处理), #pragma(实现相关), #(转义),##(参数连接)。
宏定义的注意事项
试图使用宏去定义注释符号是不行的,例如以下代码:
#define BSC // #define BMC /* #define EMC */ BSC my single-line comment BMC my multi-line comment EMC
因为注释先于预处理指令处理,当展开这些宏定义的时候自然会出现一堆错误。
宏定义表达式的时候一定不能吝啬括号。这个不用解释了。
宏定义的时候宏名中最好不要有空格。下面的定义会带来很多麻烦:
#define SUM (x) ((x)*(x))
一旦使用了#undef撤销宏,则后面的代码都不能使用这个宏,除非再次定义。此外,如果没有#undef的情形下就直接再次定义,后来的定义会覆盖掉前面的定义。下面代码中的c值是4:
#include <stdio.h> #define X 3 #define Y X*2 #undef X #define X 2 int c = Y; int main(int argc, char** argv){ printf("%d",c) ; return 0; }
宏仅在使用的时候展开,否则即使定义有问题,也不会编译出错。如果把上面代码中的第二个#define注释掉,并把C的值赋值为0,即撤销了X定义,也不会报错,因为没有使用Y,也就不会展开。
#pragma的常用参数
message:用于在编译窗口输出信息中显示对应信息。下面是一个典型的应用:
#ifdef _X86 #pragma message("x86 macro is activated."); #endif
code_seg:在开发驱动程序的时候会用到。
once: 指定(确保)仅编译一次该文件(一般是头文件)。
hdrstop:表示不编译后面的头文件。
pack:指定内存对齐参数。
#符号和##符号
#符号用于转义。这么说起来不好理解,看例子:
#define PRTSQR(x) printf("The sqr of x is %d.\n", ((x)*(x)));
如果执行PRTSQR(4),则这句代码的输出是:
The sqr of x is 16.
如果希望显示参数的值,那么在字符串中的字符x前面加一个#并加一个引号,即:
#define PRTSQR(x) printf("The sqr of "#x" is %d.\n", ((x)*(x)));
输出结果就成了:
The sqr of 4 is 16.
##运算符用于连接,例如下面的宏:
#define XNAME(n) x##n int XNAME(8);
上面的第二行代码会被展开为x8。
关于预处理符号先总结到这里。
本文出自 “飞翔的猫咪” 博客,请务必保留此出处http://flyingcat2013.blog.51cto.com/7061638/1570411
原文地址:http://flyingcat2013.blog.51cto.com/7061638/1570411