C. *_*oss 90 c coding-style c-preprocessor
在许多程序中,a #define用作与常量相同的目的.例如.
#define FIELD_WIDTH 10
const int fieldWidth = 10;
Run Code Online (Sandbox Code Playgroud)
我通常认为第一种形式优先于另一种,依靠预处理器来处理基本上是应用程序的决定.这个传统有原因吗?
Bar*_*nau 157
这有一个非常可靠的原因:const在C中并不意味着某些东西是不变的.它只是意味着变量是只读的.
在编译器需要真常量的地方(例如非VLA数组的数组大小),使用const变量,例如fieldWidth不可能.
Vov*_*ium 23
他们是不同的.
const只是一个限定符,它表示变量在运行时无法更改.但变量的所有其他功能仍然存在:它已分配存储,并且可以解决此存储.所以代码不只是将它视为文字,而是通过访问指定的内存位置来引用变量(除非它是static const,然后它可以被优化掉),并在运行时加载它的值.并且,当const变量已分配存储时,如果将其添加到标头并将其包含在多个C源中,除非将其标记为"否则",否则会出现"多符号定义"链接错误extern.在这种情况下,编译器无法针对其实际值优化代码(除非启用全局优化).
#define只需用名称替换名称即可.此外,#define可以在预处理器中使用'd常量:您可以使用它#ifdef来根据其值进行条件编译,或使用字符串化运算符#来获取其值的字符串.当编译器在编译时知道它的值时,它可以根据该值优化代码.
例如:
#define SCALE 1
...
scaled_x = x * SCALE;
Run Code Online (Sandbox Code Playgroud)
当SCALE定义为1编译器可以消除乘法,因为它知道x * 1 == x,但如果SCALE是(extern)const,它将需要生成代码来获取值并执行乘法,因为在链接阶段之前将不知道该值.(extern需要使用来自多个源文件的常量.)
与使用更接近的#define是使用枚举:
enum dummy_enum {
constant_value = 10010
};
Run Code Online (Sandbox Code Playgroud)
但是这仅限于整数值并且没有优势#define,因此它没有被广泛使用.
const当您需要从编译它的某个库中导入常量值时,它很有用.或者如果它与指针一起使用.或者,如果它是通过变量索引值访问的常量值数组.否则,const没有优势#define.
R..*_*R.. 14
原因是大多数时候,你想要一个常数,而不是一个const合格的变量.这两者在C语言中并不相同.例如,变量作为static-storage-duration对象的初始值设定项的一部分无效,作为非vla数组维度(例如结构中数组的大小或C99之前的任何数组).
扩展R的答案一点:fieldWidth不是一个恒定的表达 ; 这是一个const合格的变量.它的值直到运行时才建立,因此不能在需要编译时常量表达式的地方使用它(例如在数组声明中,或在switch语句中使用case标签等).
与宏相比FIELD_WIDTH,预处理后的宏扩展为常量表达式10; 这个值是在编译时已知的,所以它可用于阵列的尺寸,壳体标签等
要添加到R.和Bart的答案:在C中只有一种方法可以定义符号编译时常量:枚举类型常量.该标准规定这些是类型int.我个人会把你的例子写成
enum { fieldWidth = 10 };
Run Code Online (Sandbox Code Playgroud)
但我猜C程序员的口味差异很大.