编程C开发者

谈谈在C语言中,使用const和#define定义常量的关键区别。何时以及为什么使用每种方法,并举例说明典型错误?

用 Hintsage AI 助手通过面试

答案。

#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定义了常量(复制粘贴)。结果是模块使用了不同的常量,仅在仔细调试后才修复的数据不一致。