• 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)

  • 相关阅读:
    批处理命令系列
    CMD批处理之PC查看连过的WIFI密码
    数据结构与算法之各种方法遍历二叉树
    二叉树同构判定算法
    卡拉兹(Callatz)猜想
    Java之字符串比较大小
    Java报错之StackOverflowError
    火绒勒索病毒诱捕技术浅析
    数据结构与算法之二叉链树
    数据结构与算法之广义表的基本运算
  • 原文地址:https://www.cnblogs.com/wan0807/p/4938734.html
Copyright © 2020-2023  润新知