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