8.1 宏定义
预备知识:
一个项目可以通过编译、连接最终形成一个可执行文件。
每个源文件(.cpp),都会单独编译,编译成一个目标文件(.o,也可能是.obj,扩展名跟操作系统有关)。
系统把这些.o文件进行链接,最终形成一个可执行文件。
编译干了什么事?笼统的说:词法、语法分析,目标文件,.o/, .obj的生成,优化之类的。这个编译我们可以拆开来看它干了几个事,一般来讲他会
1.预处理
2.编译
编译:词法、语法分析,目标代码生成,优化,产生一些临时文件。
3.汇编
汇编:产生.o(.obj)目标文件。
预处理是干什么的?咱们在源程序.cpp中加入一些特殊的代码(特殊的命令),这些特殊代码有一些特殊的能力,提供一些特殊功能。
编译系统会先对这些特殊代码做处理,这个就叫“预处理”,处理结果再和源程序代码一起进行上边 的2.的编译,3.汇编这一系列操作。
C语言一般提供三种预处理功能:1.宏定义; 2.文件包含 3.条件编译。
这三种功能也是通过在程序代码中写代码来实现,只不过这些代码比较特殊,都是已 # 开头。
一.不带参数的宏定义
不带参数的宏定义:用一个指定的标识符代表一个字符串。
1.一般形式:
#define 标识符/宏名 字符串 //标识符也叫宏名
2.好处:
1.用一个简单的名字代替一个长的字符串,所以这个标识符也叫宏名,在预编译时,将宏名替换为字符串的过程叫做“宏展开”。
#define 就是宏定义命令
2.增加了修改的方便性,为修改提供了极大的便利,这种便利被很频繁的使用。这也叫提高了程序的可移植性。
3.说明:
1.宏名一般都用大写字母。这是一种习惯。
2.宏定义不是c语句,所以不必在行末加分号,如果加分号则会连分号被一起替换。
3.#define命令出现在程序中函数的外面(一般在.cpp文件最上面),宏名的有效范围是#define之后,到本源文件结束。不能跨文件使用。
4.可以用#undef命令终止宏定义的作用域。
5.用#define进行宏定义时,还可以引用已经定义的宏。
#define IP 3.1415926
#define PD 5.689
#define IPPD IP*PD
6.字符串内的字符,即使与宏名相同,也不进行替换
char a = “IPPD”;
二.带参数的宏定义
一般形式如下:
#define 宏名(参数表) 字符串 //也是用右边的“字符串”代替 “宏名(参数表)”
#define S(a,b) a*b
#define K(a,b) a*2
int main()
{
S(2,3); //把2,3分别代替宏定义中的形式参数a,b ==> S(2,3) ==> 2*3
//一般“字符串中”都会包含参数表中所指定的参数,但不包含也可以,但是你若不包含,你通过参数表传进去这个参数没有意义。
K(3,4); //3*2
return 0;
}
总结:带参数的宏定义是这样展开置换的:
对一般形式中这个“字符串”,如果字符串中有宏名后列出的参数比如(a,b),则将程序语句中相应的实参(常量,变量,表达式)代替形参,
如果字符串中的字符不是参数字符,则保留。
#define PI 3.14
#define S(r) PI*r*r
int main()
{
float area = S(3); //3.14*3*3
//一般“字符串中”都会包含参数表中所指定的参数,但不包含也可以,但是你若不包含,你通过参数表传进去这个参数没有意义。
K(3,4); //3*2
return 0;
}
说明:
1.如果输入
area = S(1+5); // 3.14 *1 + 5 * 1 + 5 ,与3.14 (1 + 5 ) (1 + 5 )
在形式参数前面加括号就行了
#define S(r) PI * (r) * (r )
2.宏定义时宏名和带参数的括号之间不能加空格,否则,空格以后的字符都作为替代字符串的一部分了。
#define S (r) PI * (r) * (r )
area = S(1+5) // (r) PI* (r) *(r)(1+5)
三.宏定义和函数的区别
1.函数调用时先求出实参表达式的值,然后带入形参;带参数的宏只进行简单的字符替换,并没有求表达式的值等行为发送。
2.函数调用时在程序运行时处理,分配临时内存。宏展开是在编译时进行的,展开时不分配内存,也没有返回值这种说法,也没有值传递的说法。
3.宏的参数没有类型这个说法,只是个符号,展开时带入指定字符串。
4.使用宏次数多时,宏展开后源程序变长,函数调用不会使源程序变长。
5.宏替换只占用编译时间,不占用运行时间。函数调用占用运行时间(分配内存,传递参数,执行函数体,返回值)。
//宏替换复杂语句
#define MAX(x,y) (x)>(y)?(x):(y)
//宏替换多行语句
#define MACROTEST do{ \
printf("test\n");\
}while(0)
int main()
{
MACROTEST;
return 0;
}
#define MACROTEST do{ \
printf("test\n");\
}while(0);
int main()
{
MACROTEST
return 0;
}