为什么大多数C开发人员使用define而不是const?

为什么大多数C开发人员使用define而不是const?,c,coding-style,c-preprocessor,C,Coding Style,C Preprocessor,在许多程序中,#define的作用与常量相同。比如说 #define FIELD_WIDTH 10 const int fieldWidth = 10; 我通常认为第一种形式比另一种更受欢迎,依靠预处理器来处理基本上是应用程序决策的内容。这种传统有什么原因吗?原因是在大多数情况下,您需要的是一个常量,而不是一个限定变量。这两种语言在C语言中并不完全相同。例如,变量作为静态-存储持续时间对象的初始值设定项的一部分,作为非vla数组维度(例如结构中数组的大小,或C99之前的任何数组)无效。这有一个

在许多程序中,
#define
的作用与常量相同。比如说

#define FIELD_WIDTH 10
const int fieldWidth = 10;

我通常认为第一种形式比另一种更受欢迎,依靠预处理器来处理基本上是应用程序决策的内容。这种传统有什么原因吗?

原因是在大多数情况下,您需要的是一个常量,而不是一个限定变量。这两种语言在C语言中并不完全相同。例如,变量作为
静态
-存储持续时间对象的初始值设定项的一部分,作为非vla数组维度(例如结构中数组的大小,或C99之前的任何数组)无效。

这有一个非常明确的原因:
C中的const
并不意味着某些东西是常量。它只是意味着变量是只读的

在编译器需要真常量的地方(如非VLA数组的数组大小),使用
const
变量(如
fieldWidth
)是不可能的。

根据K&R(第二版,第211页),“const和volatile属性在ANSI标准中是新的”。这可能意味着真正古老的ANSI代码根本没有这些关键字,这实际上只是一个传统问题。
此外,它说编译器应该检测更改常量变量的尝试,但除此之外,它可能会忽略这些限定符。我认为这意味着一些编译器可能不会优化包含常量变量的代码,以在机器代码中表示为中间值(如#define do),这可能会花费额外的时间来访问远内存并影响性能。

对R的答案进行一点扩展:
fieldWidth
不是一个常量表达式;它是一个
常量
限定变量。它的值直到运行时才建立,因此它不能用于需要编译时常量表达式的地方(例如在数组声明中,或在
开关
语句中的大小写标签中,等等)

与宏
字段_WIDTH
比较,预处理后该字段扩展为常量表达式
10
;此值在编译时已知,因此可用于数组维度、大小写标签等。

它们是不同的

const
只是一个限定符,表示变量不能在运行时更改。但变量的所有其他特性仍然存在:它已经分配了存储,并且这个存储可以被寻址。因此,代码不只是将其视为文字,而是通过访问指定的内存位置来引用变量(除非它是
static const
,然后可以对其进行优化),并在运行时加载其值。由于
const
变量已经分配了存储空间,如果您将其添加到一个头部并将其包含在多个C源中,您将得到一个“多符号定义”链接错误,除非您将其标记为
extern
。在这种情况下,编译器无法根据实际值优化代码(除非启用了全局优化)

#define
只是用名称的值替换名称。此外,可以在预处理器中使用
#define
'd常量:您可以将其与
#ifdef
一起使用,根据其值进行条件编译,或者使用字符串化操作符
#
获取带其值的字符串。由于编译器在编译时知道它的值,它可以基于该值优化代码

例如:

#define SCALE 1

...

scaled_x = x * SCALE;
SCALE
被定义为
1
时,编译器可以消除乘法,因为它知道
x*1==x
,但是如果
SCALE
是(
extern
常量,它需要生成代码来获取值并执行乘法,因为只有在链接阶段才能知道值。(
extern
需要使用多个源文件中的常量。)

与使用
#define
更接近的等效方法是使用枚举:

enum dummy_enum {
   constant_value = 10010
};
但它仅限于整数值,并且没有
#define
的优点,因此没有得到广泛应用


const
在需要从编译常量的库中导入常量值时非常有用。或者如果它与指针一起使用。或者,如果它是通过变量索引值访问的常量值数组。否则,
const
#define

相比没有任何优势,可以添加到R.和Bart的答案中:在C中定义符号编译时常量只有一种方法:枚举类型常量。该标准规定这些类型为
int
。我个人会把你的例子写成

enum { fieldWidth = 10 };

但是我猜C程序员的口味在这方面有很大的不同。

虽然常量int并不总是合适的,但是如果你定义某个值为整数值,枚举通常会替代#define。在这种情况下,这实际上是我的偏好

enum { FIELD_WIDTH = 16384 };
char buf[FIELD_WIDTH];
在C++中,这是一个巨大的优势,因为你可以在类或命名空间中扩展你的枚举,而你不能限定一个定义。
在C语言中,你没有名称空间,不能在结构中定义枚举,甚至不能确定你是否得到了类型安全性,所以我看不出有什么主要的优势,尽管那里的一些C程序员可能会向我指出。

一些C编译器会将所有的
常量
变量存储在二进制文件中,如果准备的话,可能会占用嵌入式世界中的大量空间


相反:使用
const
允许在现有程序上闪烁以更改特定参数。

在C中定义数值常量的最佳方法是使用enum。请阅读相应的K&R的C语言编程章节,第39页。< /P> + 1,在不知道C.@ C.罗斯:一致性的C++程序员中,在错误的海中进行正确的回答。所有清单常量通常用
#define
s定义<代码>常量
仅用于指示读操作