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

时间:2010-10-26 13:51:11

标签: c coding-style c-preprocessor

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

#define FIELD_WIDTH 10
const int fieldWidth = 10;

我经常看到第一种形式优先于另一种形式,依靠预处理器来处理基本上是应用程序的决定。这个传统有原因吗?

9 个答案:

答案 0 :(得分:152)

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

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

答案 1 :(得分:20)

他们是不同的。

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

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

例如:

#define SCALE 1

...

scaled_x = x * SCALE;

SCALE定义为1时,编译器可以消除乘法,因为它知道x * 1 == x,但SCALEextern} { {1}},它需要生成代码来获取值并执行乘法,因为在链接阶段之前不会知道该值。 (const需要使用来自多个源文件的常量。)

与使用extern相当的更接近的是使用枚举:

#define

但这仅限于整数值,并且没有enum dummy_enum { constant_value = 10010 }; 的优点,所以它没有被广泛使用。

当您需要从编译它的某个库中导入常量值时,

#define非常有用。或者如果它与指针一起使用。或者,如果它是通过变量索引值访问的常量值数组。否则,const优于const

答案 2 :(得分:13)

原因在于,大多数情况下,您需要一个常量,而不是const - 限定变量。这两者在C语言中并不相同。例如,变量作为static - storage-duration对象的初始值设定项的一部分无效,作为非vla数组维度(例如结构中数组的大小,或C99之前的任何数组)。 / p>

答案 3 :(得分:8)

扩展R的答案:fieldWidth不是常量表达式;它是一个const - 限定变量。它的直到运行时才建立,因此不能在需要编译时常量表达式的地方使用它(例如在数组声明中,或switch中的案例标签声明等)。

与宏FIELD_WIDTH比较,后预处理扩展为常量表达式10;此值在编译时已知,因此可用于数组维度,案例标签等。

答案 4 :(得分:6)

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

enum { fieldWidth = 10 };

但我猜C程序员的口味差异很大。

答案 5 :(得分:4)

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

enum { FIELD_WIDTH = 16384 };
char buf[FIELD_WIDTH];

在C ++中,这是一个巨大的优势,因为您可以将枚举范围限定在类或命名空间中,而不能使用#define。

在C中你没有命名空间,也不能在结构中使用枚举范围,甚至不确定你是否获得类型安全性,所以我实际上看不到任何主要优势,尽管可能有些C程序员会指出它对我说。

答案 6 :(得分:2)

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

答案 7 :(得分:1)

某些C编译器会将所有const变量存储在二进制文件中,如果准备a large list of coefficients,则可能会占用嵌入式世界中的大量空间。

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

答案 8 :(得分:0)

在C中定义数字常量的最佳方法是使用 enum 。阅读K& R的C编程语言的相应章节,第39页。