c++中的数值常数

Numerical constant in C++

本文关键字:常数 c++      更新时间:2023-10-16

我看到很多关于静态const、#define和enum之间应该选择哪一个的问题。

没有讨论在嵌入式系统中很重要的资源方面。

我不喜欢使用#define,但它不像static那样消耗资源。关于enum,在消耗RAMROM吗?

此外,我被告知,如果我使用例如const int,它将不会消耗RAM或ROM,假设我不使用指针引用这个变量。这是真的吗?

如果这是真的,为了节省资源,在namespace中使用const int不是一个很好的解决方案吗?

备注:我使用的是c++ 2003标准,不能使用2011标准。(我已经看到enum class和constexpr在2011年,但我不能使用它们)

…如果我使用例如const int,它将不会消耗RAM或ROM, 假设我不使用指针引用到此变量

。如果使用#defineenum,编译器没有理由将常量放入数据内存中——它总是将其放入代码中。如果你使用const int,编译器只会在你的代码没有引用它(即当它没有使用odr时)时才会做同样的事情。

有一些看起来很友好的结构,它们默默地将引用引入到您的代码中,因此在实践中,您不能假设const int的行为方式与enum相同。例如:

const int UNIVERSE = 42;
int calc = ...;
int answer = max(calc, UNIVERSE);

如果您从std名称空间使用max(就像您应该的那样),它将在您的代码中引入constUNIVERSE的引用,这可能将42添加到您的数据ROM中。也

:

bool condition = ...;
int answer = condition ? 0 : UNIVERSE;

这里也有同样的问题(详见这里);您的代码可能const int上的行为与#defineenum中的任何一个都不同。

c++ 11引入了constexpr,它将避免这些微妙的问题。因此,如果您不能使用c++ 11并希望获得最大性能(或最小内存浪费),则应该使用#defineenum。此外,如果您希望常量的类型不是int,则必须使用#define:

#define UNIVERSE (uint64_t)42

你的假设毫无意义。所有的数据都必须存储在某个地方。你不能在空气中存储数据。

#defineconst的区别在于前者倾向于将常量嵌入到代码内存中,而后者可能会在数据内存中为变量提供专用地址。在任何一种情况下,它们都将消耗相同数量的内存量。

如果你不启用任何编译器优化,然而,在数据内存中存储在专用地址的变量可能会导致内存消耗的微小变化,如果在这种情况下,获取数据的指令也可能包含原始值。

但是这些微优化不是你应该考虑的。我们说的是ROM存储器,你应该有足够的ROM存储器。

在固定地址上分配这些常量的优点是,您可以获取它们的地址并在调试器中查看它们的值。所以它们不一定与#defined相同。

程序不使用的变量将被优化掉。

类型的定义本身不消耗内存(ROM);除了调试信息(如果有的话)。

所以简单;

enum MyValues {
  Value1,
  Value2
};

不会占用ROM,但是,该类型的实例化(实际对象)会占用内存(先从ROM加载,然后再从RAM加载)。

MyValues val1 = Value1;

上面,val1占用内存

那么与#defineconst int替代方案有什么区别呢?

清晰。

预处理器(使用#define)和编译器(使用const int)足够聪明,在大多数情况下可以做几乎完全相同的事情(除了获取const int的地址之类的事情)。enum是将相关值组合在一起的语言结构,它不是唯一的,但它是一个非常自然的结构。