C语言三种预处理功能
宏定义(#define)
宏定义又称为宏代换、宏替换,简称“宏”。
不带参数
格式:define 标识符 字符串
其中标识符就是所谓的符号常量,也称为“宏名”。例:
#define Pi 3.1415926//把程序中出现的Pi全部换成3.1415926
说明:
- 宏名一般用大写;
- 使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义;
- 预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查;
- 宏定义末尾不加分号;
- 宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头;
- 可以用#undef命令终止宏定义的作用域;
- 宏定义允许嵌套;
- 字符串( ” ” )中永远不包含宏;
- 宏定义不分配内存,变量定义分配内存;
- 宏定义不存在类型问题,它的参数也是无类型的。
带参数
格式:
#define 宏名(参数表) 字符串
例如:
#define S(a,b) a*b area=S(3,2);//第一步被换为area=a*b; ,第二步被换为area=3*2;
- 实参如果是表达式容易出问题,
#define S(r) r*r area=S(a+b);//第一步换为area=r*r;,第二步被换为area=a+b*a+b;
最好给表达式中的参数都加上(),正确的宏定义是
#define S(r) ((r)*(r))
宏名和参数的括号间不能有空格;
只作替换,不做计算,不做表达式求解;
函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存
宏的参数不存在类型,也没有类型转换。(类型转换由编译器在进行编译时负责)
宏展开使源程序变长,函数调用不会
宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)。
#undef
作用:在后面取消以前定义的宏定义。一旦标识符被定义成一个宏名称,它将在作用域内保持已定义状态,直到程序结束或者使用#undef 指令取消定义。例:
#define TEST_A 1 #include "TEST.h" #undef TEST_A
说明:在文件#include “TEST.h” 中宏定义
#define TESTA 1
起作用,过了这一语句宏定义就释放掉了,在test.h里,这个宏是有效的,然后出了这个头文件,又无效了。
文件包含(#include)
其一般形式为:
#include "filename"
尖括号表示预处理到系统规定的路径中去获得这个文件(即C 编译系统所提供的并存放在指定的子目录下的头文件)。找到文件后,用文件内容替换该语句。
或
#include <filename>
双引号表示预处理应在当前目录中查找文件名为filename 的文件,若没有找到,则按系统指定的路径信息,搜索其他目录。找到文件后,用文件内容替换该语句。
条件编译(#if、#else、#endif、#elif、#line、#pragma )
一般形式有
如果表达式为真,就编译语句段1,否则编译语句段2
#if表达式 //语句段1 #else //语句段2] #endif
如果表达式1真,则编译语句段1,否则判断表达式2;如果表达式2为真,则编译语句段2,否则编译语句段3
#if表达式1 //语句段1 #elif表达式2 //语句段2 #else //语句段3 #endif
如果在此之前已定义了这样的宏名,则编译语句段。
#ifdef 宏名 //语句段 #endif
如果在此之前没有定义这样的宏名,则编译语句段。
#ifndef宏名 //语句段 #endif
else可以用于#ifdef和#ifndef中,但#elif不可以。
pragma 预处理指令
格式: #pragma Para pragma message(“消息文本”) 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。 pragma once 只要在头文件的最开始加入这条指令就能够保证头文件被编译一次 pragma warning pragma warning(disable:450734)//不显示4507和34号警告信息;#pragma warning(once:4385)//4385号警告信息仅报告一次;#pragma warning(error:164)//把164号警告信息作为一个错误。 等价于#pragma warning(disable:450734;once:4385;error:164)。#pragma warning(push)保存所有警告信息的现有的警告状态。#pragma warning(push,n)保存所有警告信息的现有的警告状态,并且把全局警告等级设定为n。#pragma warning(pop)恢复所有的警告信息 pragma push_macro 将指定的宏压入栈中,相当于暂时存储,以备以后使用 pragma pop_macro 将栈顶的宏出栈,弹出的宏将覆盖当前名称相同的宏 pragma deprecated warning C4995: “….” : 名称被标记为 #pragma deprecated这个错误意思是说,某个函数已经被标记为过时了,最好不要用,在将来的版本中,该函数可能就不存在了,可能会被更好的函数替代 … # line
这个宏通常是和__LINE__
宏一起使用的,__LINE__
宏表示当前c语句在源文件中的行数,举个例子来说明 #line宏的使用:#include "iostream" #line 100 using namespace std; int main(int argc, char* argv[]) { cout<<"LINE:"<<LINE<<endl; return 0; } //输出结果是:__LINE__:104
本来应该是输出:
__LINE__:7
,因为cout<<"__LINE__:"<<__LINE__<<endl;
语句在第7行;但是有了#line 100
,则从#line 100
所在行的下一行被认为是第100行,所以输出的行号是104了。