const与#define对全局常量的主要优点是什么?
例如,在嵌入式编程中,# #define GLOBAL_CONSTANT 42
优于const int GLOBAL_CONSTANT = 42;
原因如下:
- 它不需要放在RAM中(在微控制器中通常非常有限,μC应用通常需要大量的全局常量)
-
const
不仅需要flash中的存储位置,而且编译器会在程序开头生成额外的代码来复制它。
反对使用#define
所有这些优点,使用const
的主要优点是什么? 在非μC环境中,内存通常不是一个大问题,而const
很有用,因为它可以在本地使用,但是全局常量呢? 或者答案只是“我们永远不应该使用全局常量”?
编辑:
这些例子可能引起了一些误解,所以我必须声明它们在C中。如果C编译器为两者生成了完全相同的代码,我认为这将是一个错误,而不是一个优化。
为了获得新的见解,我只是将问题扩展到C ++而不考虑它,但我很清楚,在面向对象的环境中,全局常量的空间很小,无论它们是宏还是consts。
对于C和C ++,您的问题的答案各不相同。
在C中, const int GLOBAL_CONSTANT
在C中不是常量 ,因此在C中定义真常量的主要方法是使用#define
。
在C ++中,使用const
不是#define
一个主要优点是#defines
不遵守范围,因此无法创建类范围的命名空间。 虽然const变量可以在类中作用域。
除此之外还有其他微妙的优点,如:
在编译错误期间避免奇怪的魔法数字:
如果您正在使用#define
,那么在预编译时它们会被预处理器替换。因此,如果您在编译期间收到错误,它将会引起混淆,因为错误消息不会引用宏名称而是值,它将显示为突然值一个人会浪费很多时间在代码中跟踪它。
易于调试:
同样出于#2中提到的相同原因,调试时#define
也没有提供任何帮助。
你确定你的编译器太笨了,无法通过在需要的地方插入值而不是将其放入内存来优化常量吗? 编译器通常具有良好的优化性。
常量与宏的主要优点是常量具有范围。 宏在任何地方都被替换,不考虑范围或上下文。 它导致很难理解编译器错误消息。
调试器也不知道宏。
更多可以在这里找到
尚未提及的另一个原因是const
变量允许编译器执行显式类型检查,但宏不允许。 使用const
可以帮助防止通常难以调试的细微的数据相关错误。
我认为主要的优点是你可以改变常量,而不必重新编译使用它的所有东西。
由于宏更改将有效地修改使用宏的文件的内容,因此需要重新编译。
在C中, const
限定符不定义常量,而是定义只读对象:
#define A 42 // A is a constant const int a = 42; // a is not constant
在需要实常数的地方不能使用const
对象,例如:
static int bla1 = A; // OK, A is a constant static int bla2 = a; // compile error, a is not a constant
请注意,这在C ++中是不同的,其中const
确实将对象限定为常量。
用const
列出的唯一问题总结为“我有可能想象的最无能的编译器”。 然而,# #define
的问题是普遍的 – 例如,没有范围。
在C ++中没有理由使用#define
而不是const int
。 任何像样的C ++编译器都会以与#define相同的方式替换const int中的常量值。 当以相同的方式使用时,两者都采用大约相同的闪光量。
使用const
确实允许您获取值的地址(宏没有)。 此时,行为明显偏离了宏的行为。 const现在需要程序中的空间在闪存和RAM中生存,以便它可以有一个地址。 但这真的是你想要的。
这里的开销通常是额外的8个字节,与大多数程序的大小相比很小。 在达到此级别的优化之前,请确保已用尽所有其他选项,如编译器标志。 使用编译器仔细优化大小而不使用C ++中的template
s之类的东西将节省超过8个字节。