#define 是一种预处理指令,它在编译之前将所有出现的标识符替换为值。它不创建变量,不知道类型,不检查边界,也不尊重作用域。
const 是一种修饰符,它创建一个真正的变量,但在初始化后被锁定为只读。const变量具有类型、作用域,参与调试,且更加安全。这些变量存放在.rodata段或栈/内存中。
#define — 用于编译阶段所需的简单标量值,特别是在预处理条件或数组大小中使用(#define SIZE 16)。const — 用于需要类型安全传递、调试,并安全导出(在头文件中,跨模块)的值。const。示例:
#define PI 3.14159 const double G = 9.81; int arr[PI]; // 错误!PI 不是整数 int arr2[G]; // 错误!G 不是编译时常量
问题: const int a = 10; 在创建数组时是否作为编译时常量工作:int arr[a];?
答案: 不。在C语言中,const是一个修饰符,但变量是在运行时创建和初始化的,而不是在编译时,因此数组的大小必须是字面量或编译器已知的表达式。请使用#define,或 enum { SIZE = 10 };。
错误示例:
const int a = 5; int arr[a]; // 在C89/90中不适用(VLA在C99中引入,但并不普遍支持)
历史
在媒体服务器中,尝试使用
const int来定义缓冲区的大小,以为这是“编译时常量”。在一个编译器(GCC,C99)上都能正常工作,但在大多数编译器上却出现编译错误(VLA不支持),急忙改回# define。
历史
在平台依赖的代码中通过
#define NAME "MyApp"定义了一个字符串,在多个地方使用时忘记加括号。添加字符到字符串时没有显式括号导致了错误结果,从而在日志中引发奇怪的bug。
历史
在一个具有多个模块的项目中,在两个地方以不同的值通过#define定义了常量(复制粘贴)。结果是模块使用了不同的常量,仅在仔细调试后才修复的数据不一致。