为什么大多数C开发人员使用define而不是const?
在许多程序中,# #define
与常量具有相同的用途。 例如。
#define FIELD_WIDTH 10 const int fieldWidth = 10;
我通常会看到第一种forms比其他forms更受欢迎,依靠预处理器来处理基本上是应用程序决策的内容。 这个传统有什么理由吗?
这有一个非常可靠的原因:C中的const
并不意味着一些常量。 这只是意味着一个variables是只读的。
在编译器需要一个常量的地方(例如非VLA数组的数组大小),使用const
variables(如fieldWidth
是不可能的。
他们不一样
const
只是一个限定符,它表示一个variables在运行时不能被改变。 但variables的所有其他function仍然存在:已经分配了存储空间,并且可以解决此存储空间问题。 因此,代码不仅仅把它当作一个文字来对待,而是通过访问指定的内存位置来引用variables(除非它是static const
,那么它可以被优化掉),并且在运行时加载它的值。 而作为一个const
variables已经分配了存储空间,如果你把它添加到一个头文件中,并将它包含在几个C源代码中,除非将其标记为extern
否则将会出现“多符号定义”链接错误。 在这种情况下,编译器无法根据实际值优化代码(除非进行全局优化)。
#define
只是用它的值replace一个名字。 此外,可以在预处理器中使用#ifdef
常量:可以使用#ifdef
根据其值进行条件编译,也可以使用string化运算符#
来获取string的值。 而且由于编译器在编译时知道它的值,所以可以根据这个值优化代码。
例如:
#define SCALE 1 ... scaled_x = x * SCALE;
当SCALE
被定义为1
,编译器可以消除乘法,因为它知道x * 1 == x
,但是如果SCALE
是( extern
) const
,则需要生成代码来获取值并执行乘法,因为值直到连接阶段才会知道。 ( extern
需要使用来自多个源文件的常量。)
更接近于使用#define
使用枚举:
enum dummy_enum { constant_value = 10010 };
但是这只限于整数值,并没有#define
优点,所以没有被广泛的使用。
当你需要从编译它的某个库中导入一个常量值的时候, const
是很有用的,或者如果它和指针一起使用的话。 或者,如果它是通过variables索引值访问的常量值数组。 否则, const
比#define
没有任何优势。
原因是大多数时候,你想要一个常量,而不是一个const
限定的variables。 在C语言中,这两者并不是相同的。 例如,variables作为static
持续时间对象的初始值设定项的一部分无效,例如非vla数组维度(例如结构中的数组大小或任何数组前C99)。
在R的答案稍微扩展一下: fieldWidth
不是一个常量expression式 ; 这是一个const
限定variables。 它的值直到运行时才build立,所以在需要编译时常量expression式的地方(比如在一个数组声明中,或者在一个switch
语句中的一个case标签等),它不能被使用。
与预处理后扩展为常量expression式10
的macrosFIELD_WIDTH
比较; 这个值在编译时是已知的,所以它可以用于数组维度,案例标签等。
要添加到R.和Bart的答案:在C:枚举types常量中只有一种方法来定义符号编译时间常量。 这个标准规定这些是int
types的。 我个人会写你的例子
enum { fieldWidth = 10 };
但是我觉得C程序员的口味差别很大。
虽然const int并不总是合适的,但是如果你定义了一个整型值,枚举通常会作为#define的替代。 这实际上是我在这种情况下的首选。
enum { FIELD_WIDTH = 16384 }; char buf[FIELD_WIDTH];
在C ++中,这是一个巨大的优势,因为您可以将枚举的范围限定在类或名称空间中,而不能将范围定义为#define。
在C中,你没有命名空间,也不能在一个结构体内枚举枚举的范围,甚至不能确定你的types是否安全,所以我实际上看不到任何主要的优点,尽pipe也许有些C程序员会指出。
根据K&R(第2版,第211页),“const和volatile属性是ANSI标准新增的”。 这可能意味着真正旧的ANSI代码根本就没有这些关键字,这实际上只是一个传统问题。 此外,它表示,编译器应该检测到更改constvariables的尝试,但除此之外可能会忽略这些限定符。 我认为这意味着一些编译器可能不会优化包含constvariables的代码,以便在机器代码中表示为中间值(就像#define一样),这可能会花费额外的时间访问远端内存并影响性能。
一些C编译器会将所有const
variables存储在二进制文件中,如果准备大量的系数可以在embedded式世界中占用大量的空间。
相反:使用const
允许在现有的程序上闪烁来改变特定的参数。
在C中定义数字常量的最好方法是使用枚举 。 阅读K&R的The C Programming Language,第39页的相应章节。