模块一 · 入门基础 / 第 03 课
03 · 常量与 #define
学习目标
- 会用 #define 给常数起名字
- 理解宏只是「文本替换」
- 知道 const 的基本用法
为什么不要到处写裸数字
写 pi = 3.14 没问题,但代码里到处散落 3.14、7、100,半年后你自己都看不懂。更好的做法:
#include <stdio.h>
#define PI 3.14159
#define MAX_SCORE 100
int main(void)
{
double r = 2.0;
printf("面积 = %f\n", PI * r * r);
printf("满分 = %d\n", MAX_SCORE);
return 0;
}
#define 的本质
编译前,预处理器会把代码里的宏名原样换成后面的文本。它不是变量,不占运行时的「盒子」。
注意
宏结尾没有分号。写成 #define N 10; 会把分号也替换进去,容易出怪错。const 常量
需要「有类型、像变量一样用,但不能改」时用 const:
const int DAYS = 7;
// DAYS = 8; // 编译报错:不能修改 const
const double G = 9.8; /* 重力加速度也可以是 const */
带参数的宏(了解即可)
宏还可以「带参数」,本质仍是文本替换。写时一定要多加括号,否则容易算错:
#include <stdio.h>
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
int main(void)
{
printf("%d\n", SQUARE(3)); /* 9 */
printf("%d\n", MAX(10, 20)); /* 20 */
/* 若写成 #define SQUARE(x) x*x,则 SQUARE(1+2) 会变成 1+2*1+2 = 5,不是 9 */
return 0;
}
易错点小结
这三件事最容易忘
- 宏名一般全大写,和变量区分开
#define行末不要加分号- 宏没有类型检查,复杂逻辑更推荐写成函数
单片机场景 · 宏定义:名称表达硬件含义
用名字代替魔法数字。数值常量和硬件别名要分清,宏本身不会创建变量。
边界与验证:LED_ON = 0 只是假设低电平有效,须核对电路。原文 LED_PORT 对 P1 的别名仅适用于存在 P1 定义的目标环境。
#define MAX_COUNT 100
#define LED_ON 0
#define LED_OFF 1
unsigned int cnt = 101;
if (cnt > MAX_COUNT) {
cnt = 0;
}
本课过关
必做#define MAX 100 的作用是?
逐步解析
#define 发生在编译之前的预处理阶段:编译器先把源文件里的 MAX 全部替换成文本 100,然后再编译。所以 MAX 不是变量,没有地址,也不占运行内存;你也不能对它取地址或修改。这和 const int 不同——const 是真正的只读变量,有类型、有存储。选宏还是 const:简单常数两者都行;需要类型安全或取地址时用 const。
必做作业
- 用 #define 定义圆周率和一周天数,写个小程序打印。
- 为什么宏名通常全大写?
- 把 MAX 定义成 100 后,写 if (score > MAX) 有何好处?
先自己写完,再点开看解答
1:综合题参考
#include <stdio.h>
#define PI 3.1415926
#define WEEK_DAYS 7
int main(void)
{
double r = 1.5;
printf("周长相关:一周有 %d 天\n", WEEK_DAYS);
printf("圆面积 = %f\n", PI * r * r); /* 面积 πr² */
return 0;
}2:为什么全大写:约定。读代码时一眼能看出「这是宏,不是可改的变量」,也避免和局部变量重名混淆。
3:宏的好处:满分若从 100 改成 120,只改一行 #define;全文里的 MAX_SCORE 都变了。若散落写死 100,就要全局搜索,还容易漏。
学完去哪
下一课:运算符——程序会算数、会比较。