C ++中的数值常量

时间:2016-08-28 15:49:15

标签: c++ enums embedded

我看到很多关于static const vs #define vs enum之间应该首选的问题。

在所有这些方面都没有讨论资源方面,这在嵌入式系统中非常重要。

我不喜欢使用#define,但它不会消耗static之类的资源。那么enum,消耗RAM \ ROM呢?

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

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

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

3 个答案:

答案 0 :(得分:1)

  

...如果我使用例如const int它不会消耗RAM或ROM,假设我没有使用指针\ reference 来此变量

完全。如果使用#defineenum,编译器没有理由将常量放在数据存储器中 - 它总是将它放在代码中。如果使用const int,编译器将只执行相同的操作(主要是?),如果您的代码没有引用它(即当它不是ODR使用时)。

有一些看似良性的构造会默默地在您的代码中引入引用,因此在实践中,您不能认为const int的行为方式与enum相同。例如:

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

如果您使用max命名空间中的std(就像您应该这样),它会向您的代码引入const UNIVERSE个引用,其中可能将42添加到数据ROM中。

此外:

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

此处存在同样的问题(详见here);您的代码可能const int的行为不同#defineenum

C ++ 11引入了constexpr,这将避免这些微妙的问题。因此,如果您不能使用C ++ 11并希望获得最大性能(或浪费的内存最少),则应使用#defineenum。另外,如果您希望常量的类型不是int,那么您仍然会遇到#define

#define UNIVERSE (uint64_t)42

答案 1 :(得分:0)

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

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

如果你没有启用任何编译器优化,那么存储在数据存储器中专用地址的变量可能会导致内存消耗的微小变化,这种情况下获取该数据的指令可以同时包含了原始价值。

但是这些微观优化并不是你应该考虑的事情。我们在谈论ROM内存,你应该有很多。

在固定地址分配此类常量的优点是,您可以获取其地址并在调试器中查看其值。所以它们与#defined个不一样。

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

答案 2 :(得分:0)

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

所以,简单地说;

enum MyValues {
  Value1,
  Value2
};

不会消耗ROM。但是,类型(实际对象)的实例化将消耗内存(从ROM加载,然后在RAM中加载)。

MyValues val1 = Value1;

上面,val1消耗内存。

那么#defineconst int替代方案的区别是什么?

净度。

预处理器(使用#define)和编译器(使用const int)非常聪明,在大多数情况下都可以完成相同的操作(除了获取地址之外) const int)。 enum是将相关值组合在一起的语言构造,它不是唯一的,但它是非常自然的。