C语言学习笔记九(宏定义)

1.预处理的概念

        预处理的编译就是对C语言的源程序进行编译前,有“编译预处理程序”对预处理命令进行处理的过程。

        C语言提供了多种预处理功能,如宏定义、文件包含、条件编译等。

2. 宏定义的基本概念

 宏定义是C语言预处理指令之一,使用#define指令实现,用于在编译前进行文本替换。

基本语法

#define 宏名 替换文本

 示例

#define PI 3.1415926
#define MAX_SIZE 100

3. 宏定义的分类

3.1 无参宏(对象式宏)

#define BUFFER_SIZE 1024
#define VERSION "1.0.0"

 3.2 带参宏(函数式宏)

#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))

4. 宏定义的特点

  1. 预处理阶段替换:在编译前进行文本替换

  2. 无类型检查:宏只是简单的文本替换

  3. 不分配内存:宏定义不占用内存空间

  4. 作用域从定义处到文件结束(可用#undef取消定义)

5. 带参宏的注意事项

5.1 参数括号

为避免运算符优先级问题,参数和整个表达式都应加括号:

// 错误的示例
#define SQUARE(x) x * x
// 正确的示例
#define SQUARE(x) ((x) * (x))

5.2 避免副作用

宏参数可能被多次求值,导致副作用:

#define MAX(a, b) ((a) > (b) ? (a) : (b))
int x = 1, y = 2;
int z = MAX(x++, y++); // 可能导致x或y被多次递增

5.3 多行宏定义

使用反斜杠\实现多行宏:

#define SWAP(a, b) do { \
    typeof(a) temp = a; \
    a = b;              \
    b = temp;           \
} while(0)

6. 特殊宏运算符

6.1 字符串化运算符#

将宏参数转换为字符串:

#define STR(x) #x
printf("%s", STR(hello)); // 输出 "hello"

6.2 连接运算符##

连接两个标记:

#define CONCAT(a, b) a##b
int xy = 10;
printf("%d", CONCAT(x, y)); // 输出 xy的值 10

7. 预定义宏

C语言提供了一些预定义宏:

__LINE__    // 当前行号
__FILE__    // 当前文件名
__DATE__    // 编译日期
__TIME__    // 编译时间
__STDC__    // 是否遵循ANSI C标准
__func__    // 当前函数名(C99)

8. 宏与函数的比较

特性函数
执行时机预处理阶段运行时
类型检查
开销代码膨胀调用开销
调试难以调试易于调试
参数求值可能多次求值只求值一次
适用场景简单操作、常量定义等复杂逻辑、重用代码等

9. 宏的常见用途

  1. 定义常量

  2. 条件编译

  3. 简化复杂表达式

  4. 泛型编程(通过宏模拟)

  5. 调试信息输出

  6. 平台特定代码处理

10. 最佳实践

  1. 宏名全部大写以区分变量和函数

  2. 带参宏的每个参数和整体表达式都要加括号

  3. 避免使用会产生副作用的参数

  4. 复杂逻辑优先考虑使用函数而非宏

  5. 适当使用do {...} while(0)包裹多语句宏

  6. 及时使用#undef取消不再需要的宏定义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值