为什么大多数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定义<代码>常量
仅用于指示读操作