在许多程序中,#define
的作用与常量相同。例如:
#define FIELD_WIDTH 10
const int fieldWidth = 10;
我经常看到第一种形式比另一种更受欢迎,依赖于预处理器来处理基本上是应用程序决策的内容。这个传统有什么原因吗?
在许多程序中,#define
的作用与常量相同。例如:
#define FIELD_WIDTH 10
const int fieldWidth = 10;
我经常看到第一种形式比另一种更受欢迎,依赖于预处理器来处理基本上是应用程序决策的内容。这个传统有什么原因吗?
这其中有一个非常充分的理由:const
在C语言中并不意味着某个东西是常量。它仅仅表示一个变量是只读的。
在编译器需要真正常量(例如用于非VLA数组的数组大小)的地方,使用一个const
变量,如fieldWidth
就不可能实现。
#define
来定义的。 const
只用于表示只读(访问路径)变量。我知道,在 C 中,const
实现得并不好 :-) - Bart van Ingen Schenauconst
的处理上,C 和 C++ 是非常不同的语言。在 C++ 中,const
可以用于正确的常量,但在 C 中则不行。 - Bart van Ingen Schenauconst
,也不能用于创建其他const
。例如:const uint8_t SECONDS_PER_MINUTE = 60U; const uint16_t SECONDS_PER_HOUR = 60U * SECONDS_PER_MINUTE;
。我想要一种有类型的常量(正如@Bart所写,const
并不是真正的常量)。 - Gauthierconst
只是一个修饰符,它表示变量在运行时不能被更改。但是变量的所有其他特性都保持不变:它具有分配的存储空间,并且可以访问此存储空间。因此,代码不仅将其视为文字,而是通过访问指定的内存位置(除非它是static const
,否则可以进行优化)引用变量,并在运行时加载其值。由于const
变量具有分配的存储空间,如果将其添加到标头并在多个C源中包含它,则会出现“多重符号定义”链接错误,除非将其标记为extern
。在这种情况下,编译器无法根据其实际值对代码进行优化(除非打开全局优化)。
#define
仅将名称替换为其值。此外,预处理器中可以使用#define
定义的常量:您可以将它与#ifdef
一起使用,根据其值进行条件编译,或使用字符串化运算符#
获取带有其值的字符串。由于编译器在编译时知道它的值,因此它可以基于该值优化代码。#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
在需要从编译库中导入常量值时很有用,或者与指针一起使用时。又或者是一个由变量索引值访问的常量值数组。否则,const
没有比#define
更大的优势。
#define
和 enum
之间的优势在于你可以使用 #ifdef
来测试其存在性或在 #if
中使用其值,这使得它更适用于控制构建时的选择或提供可能存在于某些平台上但不存在于其他平台上的功能。 - R.. GitHub STOP HELPING ICE#define
常量(我认为必须在编译时向gcc传递-gdb3
标志以启用此功能)。 - psmears这是因为大多数时候,您需要一个常量,而不是一个带有const
限定符的变量。在C语言中,它们并不完全相同。例如,变量无法作为static
存储期对象的初始化器的一部分,也不能用作非变长数组维度的值(例如结构体中数组的大小或任何C99之前的数组)。
const
的操作更像 Java 中的 final
,只允许一次赋值? - C. Rossconst
,而且我还处于Java学习曲线的底部)。 - John Bode补充R.和Bart的回答:在C语言中,只有一种方法可以定义符号的编译时常量:枚举类型常量。标准规定这些类型为int
。我个人会将您的示例写成:
enum { fieldWidth = 10 };
尽管const int并不总是合适的选择,但如果你要定义某个东西为一个整数值,枚举通常可以作为#define的替代品。在这种情况下,这实际上是我的首选。
enum { FIELD_WIDTH = 16384 };
char buf[FIELD_WIDTH];
strchr
来搜索字符,而不是使用strtof
,因为strtof
直到C99才被添加。 - R.. GitHub STOP HELPING ICE一些C编译器会将所有的const
变量存储在二进制文件中,如果准备大量系数列表,这将在嵌入式世界中占用大量空间。
相反地:使用const
允许在现有程序上刷写以更改特定参数。
const
变量,并在它们的地址从未被使用时将其优化掉,就像内联函数一样。 - R.. GitHub STOP HELPING ICE
\
enum {20 = 10};``。但是,如果 FIELD_WIDTH 的全局和局部定义都是枚举类型,则两个定义都可以共存(局部定义会掩盖全局定义)。 (有关此主题的更多信息,请参见 http://www.eetimes.com/discussion/programming-pointers/4023879/Enumeration-Constants-vs-Constant-Objects。) - Jochen Walter