2015-11-5 宏定义使用分析听课笔记·

注:基础的宏定义注意事项及概念不再赘述。

1、可以在预编译之后的.i文件中查看宏替换之后的代码。

2、可以利用宏定义求数组求数组元素个数。

#define DIM(array)  (sizeof(array)/sizeof(*array))

思考:这个功能可以利用函数来实现吗?

int dim(int array[])

{

return sizeof(array)/sizeof(*array);

}

我们在VS2005下对两种方法都进行了实验,利用宏定义的代码如下:

 1 #include<stdio.h>
 2 
 3 #define DIM(arr)  (sizeof(arr)/sizeof(*arr))
 4 
 5 int num[]={1,2,4,5,67,78,5};
 6 
 7 void main()
 8 {
 9 printf("%d
",DIM(num));
10 getchar();
11 }

程序运行结果为7,是正确的。

接下来我们采用函数的方法,看能否实现相同的效果:

 1 #include<stdio.h>
 2 
 3 
 4 
 5 int num[]={1,2,4,5,67,78,5};
 6 
 7 int dim(int arr[])
 8 {
 9 return sizeof(arr)/sizeof(*arr);
10 }
11 
12 void main()
13 {
14 printf("%d
",dim(num));
15 getchar();
16 }

实验结果为1,显然这不是我们预期的结果。那么问题出在哪里呢?

这是由于在C语言中,函数的数组参数会退化成一个指针。

这样就可以解释为什么结果为1了,因为在函数中arr是一个指针,在32位系统下,一个指针占4个字节,一个整数也是占4个字节,所以结果为1。

通过这个例子可以说明,宏定义还是有其用武之地的。

3、宏定义与函数的对比:

a、宏定义在预编译期被处理,编译器不知道宏定义的存在。

b、宏表达式用“实参”完全代替形参,不进行任何运算

c、宏表达式没有任何的调用开销

d、宏表达式中不能出现递归的定义。

4、关于#undef,宏定义的常量或者表达式是否有作用域限制?

先来看这样一段代码:

 1 #include<stdio.h>
 2 
 3 
 4 
 5 int f1(int a,int b)
 6 {
 7   #define _MIN_(a,b) ((a)<(b)?a:b)
 8   return _MIN_(a,b);
 9 }
10 
11 int f2(int a,int b ,int c)
12 {
13 return _MIN_(_MIN_(a,b),c);
14 }
15 
16 void main()
17 {
18 printf("%d
",f1(5,11));
19 printf("%d
",f2(5,3,2));
20 getchar();
21 }

代码运行的结果是5,2,由此我们可以发现,我们在函数f1中定义的宏,在函数f2中还可以使用。
那么假如我们把f2移到f1之前呢?我们这样试了一下,结果编译器报错,说_MIN_未定义在f2中。

这就说明,宏定义的作用域是从它定义之处开始到文件最后都可以使用,那么我们有没有什么办法来限制我们宏定义的作用域呢?这里就用到了我们的#undef关键字。

还是上面的代码,我将f1修改成这样:

 1 #include<stdio.h>
 2 
 3 
 4 
 5 int f1(int a,int b)
 6 {
 7   #define _MIN_(a,b) ((a)<(b)?a:b)
 8   return _MIN_(a,b);
 9   #undef _MIN_
10 }
11 
12 int f2(int a,int b ,int c)
13 {
14 return _MIN_(_MIN_(a,b),c);
15 }
16 
17 void main()
18 {
19 printf("%d
",f1(5,11));
20 printf("%d
",f2(5,3,2));
21 getchar();
22 }

编译器同样报错说,在f2中_MIN_未定义,这就说明我们可以通过#undef关键字来人为地限定宏定义的作用域。

5、强大的内置宏:

  宏名                      意义                           示例

_FILE_             被编译的文件名                    file.c

_LINE_                当前行号                         25

_DATE_           编译时的日期                  Jan 31 2012

_TIME_            编译时的时间                   17:01:01

_STDC_   编译器是否遵循标准C规范                1

我们可以利用上述宏定义打印日志:

#define LOG(s) printf("%s:%d %s ",_FILE_,_LINE_,s)

6、课后思考题:

下面的宏定义是什么意思?宏定义对空格敏感吗?宏“调用”对空格敏感吗?

#define f  (x)   ((x)-1)

原文地址:https://www.cnblogs.com/wan0807/p/4938734.html