C语言宏定义详解

本文详细探讨了C语言中的宏定义,从特点、宏定义函数、表达式到系统宏定义和范围,揭示了宏定义的工作原理。通过预编译命令展示了宏替换的过程,并提醒开发者注意宏定义中可能遇到的问题,如空格敏感性和避免使用含有表达式的宏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

宏定义

0.前言
  1. 本文章的程序是在linux下测试通过的
  2. 本文的分析通过了下面的命令来查看预编译结果

    gcc -E filename.c -o filename.i

    这条命令的作用是生成预处理文件filename.i

    gcc -S filename.c -o filename.s

    这条命令的作用是生成预编译文件filename.s

    gcc -c filename.c -o filename.o

    这条命令的作用是生成汇编文件filename.s

1.宏定义的特点
1.#define表达式给有函数调用的假象,却不是函数
2.#define表达式可以比函数更强大
3.#define表达式比函数更容易出错
2.宏定义函数
#define SWAP(a, b)  \
{                   \
    int temp = a;   \
    a = b;          \
    b = temp;       \
}

上面的语句会对变量直接进行覆盖
函数不是真正意义上的交换,只是复制了一份


3.宏定义表达式
  • 与函数的对比
    1.在于编译器被处理,编译器不知道宏表达式的存在
    2.用“实参”完全替代形参,不进行任何计算
    3.没有任何“调用”的开销
    4.不能出现递归定义
#define SUM(a, b) (a)+(b)
#define MIN(a, b) ((a < b) ? a : b)

int main()
{
    int a = 2,
        b = 5;
    SWAP(a, b);
    printf("%d %d\n", a, b);
    printf("%d\n", SUM(a, b));  //是期望的值
    printf("%d\n", MIN(a, b));  //是期望的值
    printf("%d\n", SUM(a, b) * SUM(a, b));  //不是期望的值
    printf("%d\n", MIN(a++, b));  //不是期望的值
    return 0;
}
  • 问题:

    为什么上面的例子中最后的printf没有出现预想的值

  • 解决:

    编译器只是对宏定义进行了替换,替换后的结果如下:

#define SUM(a, b) (a)+(b)
#define MIN(a, b) ((a < b) ? (a) : (b))

int main()
{
    int a = 2,
        b = 5;
    SWAP(a, b);
    printf("%d %d\n", a, b);
    printf("%d\n", (2)+(5));  //是期望的值
    printf("%d\n", ((2<5) ? (2) : (5)));  //是期望的值
    printf("%d\n", (2)+(5) * (2)+(5));  //不是期望的值
    printf("%d\n", ((2++<5) ? (2++) : (5)));  //不是期望的值
    return 0;
}

看了上面的预编译的程序后恍然大悟

  • 注意:

    避免在宏里面写表达式,而应该写计算数组的大小,因为函数无法做到

4.系统宏定义和范围

1.系统的宏

1.__FILE__ 被编译的文件名
2.__LINE__ 当前行号
3.__DATE__ 编译时的日期
4.__TIME__ 编译时的时间
5.__STDC__ 编译是否遵循标准c规范

2.作用:

1.可以通过宏来使用上面的系统的宏定义日志追踪
2.如果使用函数会出现行号不匹配

3.扩展:

可以使用循环语句(do{}while(0))定义宏,do里面使用接续符链接语句,把多行语句接到一行里面
//#define LOG(s) printf("%s:%d %s\n", __FILE__, __LINE__, s);

/*
需要调用time.h
localtime:将时间转化为本地时间
asctime:将时间转换为正常(原本为毫秒)
*/
#define LOG(s) do{  \
    time_t t;       \
    struct tm* ti;  \
    time(&t);       \
    ti = localtime(&t);     \
    printf("%s[%s:%d] %s\n", asctime(ti), __FILE__, __LINE__, s);   \
}while(0)

/*
int f1(int a, int b)
{
    //#define 没有作用域的限制,需要#undef来结束,限制作用域
    #define _MIN_(a, b) ((a) < (b) ? a : b)
    return _MIN_(a, b);
    #undef
}

int f2(int a, int b, int c)
{
    return _MIN_(_MIN_(a, b), c);
}
*/
void f()
{
    LOG("Enter f()...\n");
    LOG("Exit f()...\n");
}

int main()
{
    LOG("Enter main...\n");
    f();
    LOG("Exit main...\n");
    return 0;
}
5.注意:
  • 宏定义对空格比较敏感
    #define f (x) ((x)-1)
  • 说明:上式宏定义了个f,他的需要被替换为x,但是后面又有个((x)-1)没有任何定义,所以会报错。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值