14 宏

1 C语言中的宏定义

  • #define预处理器处理的单元实体之一
  • #define 定义的宏可以出现在程序的任意位置
  • #define 定义之后的代码都可以使用这个宏

2 定义宏常量

  • #define 定义的宏常量可以直接使用

  • #define 定义的宏常量本质为字面量 => 宏常量(本质是字面量)不是变量,不占用内存,这是与 const 常量(本质是只读变量)的本质区别

  • 示例1:分析下面定义的宏常量

    #define ERROR -1
    #define PATH1 "D:\test\test.c"
    #define PATH2 D:\test\test.c
    #define PATH3 D:\test\
    test.c
    
    int main()
    {
        int err = ERROR;
        char* p1 = PATH1;
        char* p2 = PATH2;
        char* p3 = PATH3;
    }
    
    • 利用预处理器分析:单步编译:gcc -E test.c -o test.i

      结果:编译正确,说明预处理器不进行语法检查,只进行宏替换

    • 宏替换后,可以看到 p2p3 语法错误:

      int err = -1;
      char* p1 = "D:\test\test.c";
      char* p2 = D:\test\test.c;
      char* p3 = D:\testtest.c;
      

3 宏定义表达式

  • #define 表达式的使用类似函数调用

  • #define 表达式可以比函数更强大

  • #define 表达式比函数更容易出错

  • 示例2:分析下面定义的宏表达式

    #include <stdio.h>
    
    #define _SUM_(a, b) (a) + (b)
    #define _MIN_(a, b) ((a) < (b) ? (a) : (b))
    // 得到一个数组的大小:C语言中无法通过一个函数得到一个数组的大小,只能通过宏
    #define _DIM_(a) sizeof(a)/sizeof(*a)
    
    
    int main()
    {
        int a = 1;
        int b = 2;
        int c[4] = {0};
    
        int s1 = _SUM_(a, b);                 // <=> int s1 = (a) + (b);
        int s2 = _SUM_(a, b) * _SUM_(a, b);   // <=> int s2 = (a) + (b) * (a) + (b);
        int m = _MIN_(a++, b);                // <=> int m = ((a++) < (b) ? (a++) : (b));
        int d = _DIM_(c);                     // <=> int d = sizeof(c)/sizeof(*c);
    
        printf("s1 = %d\n", s1);  // s1 = 3
        printf("s2 = %d\n", s2);  // s2 = 5
        printf("m = %d\n", m);  // m = 2
        printf("d = %d\n", d);  // d = 4
    
        return 0;
    }
    

4 宏表达式与函数的对比

  • 宏表达式被预处理器处理,编译器不知道宏表达式的存在;预处理器不会对宏定义进行语法检查,宏定义时出现的语法错误只能被编译器检测

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

  • 宏表达式没有任何的“调用”开销

  • 宏表达式中不能出现递归定义

    // 宏表达式的错误用法
    #define _SUM_(n) ((n > 0) ? (_SUM_(n - 1) + n) : 0)
    int s = _SUM_(10);
    

5 宏定义的常量/表达式的作用域

  • 对于宏

    • 没有作用域的限制
    • 定义完宏之后,后面的代码都可以使用
    • 作用域是针对变量和函数而言的
  • 示例3:分析宏常量/表达式的作用域

    #include <stdio.h>
    
    void def()
    {
        #define PI 3.1415926          // 定义宏常量
        #define AREA(r) r * r * PI    // 定义宏表达式
    }
    
    double area(double r)
    {
        return AREA(r);
    }
    
    int main()
    {
        double r = area(5);
    
        printf("PI = %f\n", PI);       // PI = 3.1415926 
        printf("d = 5; a = %f\n", r);  //  d = 5; a = 
        
        return 0;
    }
    

6 内置宏

含义 示例
_FILE_ 被编译的文件名 file.c
_LINE_ 当前行号 25
_DATE_ 编译时的日期 Sep 2 2020
_TIME_ 编译时的时间 10:20:18
_STDC_ 编译器是否遵循标准C规范 1
  • 示例
#include <stdio.h>
#include <malloc.h>

//申请x个类型为type的内存空间
#define MALLOC(type, x) (type*)malloc(sizeof(type)*x)

//逗号表达式,从左向右地运行:先将指针所指向的内存释放,再将指针置为空,内置的free函数只能将指针所指向的内存释放
#define FREE(p) (free(p), p=NULL)

//打印日志
#define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s)

#define FOREACH(i, m) for(i=0; i<m; i++)
#define BEGIN {
#define END   }

int main()
{
    int x = 0;
    int* p = MALLOC(int, 5);
    
    LOG("Begin to run main code...");
    
    FOREACH(x, 5)
    BEGIN
        p[x] = x;
    END
    
    FOREACH(x, 5)
    BEGIN
        printf("%d\n", p[x]);
    END
    
    FREE(p);
    
    LOG("End");
    
    return 0;
}

//输出结果
[Sep  2 2020] {test.c:22} Begin to run main code...
0
1
2
3
4
[Sep  2 2020] {test.c:36} End
posted @ 2020-09-02 21:25  nxgy  阅读(113)  评论(0编辑  收藏  举报