C - #define理解
最近学习C语言吧,看的是C程序设计语言一书,今天正好看到了C预处理那里,说到了这个#define A B。
首先这个叫做宏替换。那么以后你的程序里面写A的地方 其实就是B。
编译器在编译的时候会自动把A替换成B,而且是逐字替换。注意我说的这个逐字替换。
首先我们得知道在C里面怎么定义常量。那就是
1 #define strHello "HelloWorld\n"
而C++里面:
1 const string strHello = "HelloWorld\n";
这里C++里面也可以用#define来定义常量,但这只是为了兼容C。
C里面也有const关键字,但这是用来修饰函数的参数不能被修改,而不是定义常量。
在C里面#define 用得比较多是用来替换一段代码。比如:
1 #define sayMyHello() printf("Hello,HuangJacky")
2
3 int main()
4 {
5 sayMyHello;
6 return;
7 }
在编译的时候,编译器会悄悄把sayMyHello替换成后面那句printf,你是不会发现的。
也就是说编译器实际上是在编译下面这段代码:
1 int main()
2 {
3 printf("Hello,HuangJacky");
4 return;
5 }
这就是替换的意思。但是我们之前说的逐字替换。解释逐字替换之前我们先来看个例子:
1 #define power2(A) A*A
2
3 int main()
4 {
5 int i = 3;
6 int j = power2(i+2);
7 return;
8 }
power2是求平方。那么执行到第7行的时候 j等于多少呢?j=25么?
答案是j=11;为什么?
我们来看:首先A=i+2, 而j=A*A=i+2*i+2=3+2*3+2=11
看到什么没有?它只是将A替换成了i+2,而没有把i+2当成一个整体,又由于算术优先级的关系,所以结果就出现了误差。
那么我们该怎么修改?
1 #define power2(A) (A)*(A)
现在j=(i+2)*(i+2)=25了。
这是当年一个台湾公司的笔试题。
就这么就完了么?还有一个需要注意的地方。。。
1 #define max(A,B) ((A)>(B))?(A):(B)
2
3 int main()
4 {
5 int i = 3;
6 int j = 2;
7 int n = max(i++,j++);
8 return;
9 }
请问执行到第8行时 i,j,n分别是多少?
i=5,j=3,n=4;
想明白为什么没有?
我们将上面逐字替换就知道了。
1 n=((i++)>(j++))?(i++):(j++);
首先在比较的时候(i++)>(j++) 这个时候i=3,j=2,所以结果是true。
有了比较结果的时候由于自增运算符的缘故,现在i=4,j=3了。
比较结果是真,所以去返回三元运算符中的(i++),所以是4。
当返回后,由于自增运算符的缘故,这时i=5了。
从上面的例子我们可以看出来当宏替换的时候,虽然有括号括起来了,运算中出现了多少次A,程序就对A这个表达式执行了多少次。
上面这个例子中A出现了两次,其中比较的时候一次和返回的时候一次。所以最后i=5。
上面说了这么多#define使用时注意的地方,其实这些功能都能定义一个函数来完成,而且还不会出现上面这些问题。但是使用宏替换能节约调用函数时的堆栈开销。
最后记住 编译的时候,编译器会逐字的把宏替换的地方给换回去,然后编译。宏替换只是为了让我们节约一些写代码的时间和让代码阅读更方便。