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个字节。