C 语言书
模块一 · 入门基础 / 第 03 课

03 · 常量与 #define

入门 25 分钟 跳到过关题
学习目标
  • 会用 #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 的作用是?

必做作业
  1. 用 #define 定义圆周率和一周天数,写个小程序打印。
  2. 为什么宏名通常全大写?
  3. 把 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,就要全局搜索,还容易漏。