定义枚举类型会有很大的内存印记吗?

3

我正在使用32K内存的嵌入式设备,使用IAR EWARM v6.30的纯C语言编写。

为了使代码更易读,我想定义一些枚举类型,例如:

{RIGHT_BUTTON, CENTER_BUTTON, LEFT_BUTTON}

我不想使用0、1、2这样的值,但我担心会占用已经很少的额外内存。

所以我有两个问题: 1)我能强制枚举为short或byte类型而不是int类型吗? 2)定义枚举类型的确切内存印记是什么?

4个回答

7
在完全符合ISO C标准的情况下,枚举常量的大小和类型是signed int类型。为了优化或扩展,一些嵌入式系统编译器故意不遵守这个标准。
在ISO C++中,“枚举的基础类型是可以代表枚举中定义的所有枚举值的整数类型。”因此,编译器可以使用最小可能的类型,大多数编译器都这样做,但并不必须如此。
在您的情况下(IAR EWARM),手册明确说明: enter image description here 无需选项,事实上,您需要使用--enum_is_int来强制执行符合规范的行为。其他编译器可能会有不同的行为或不同的扩展、预处理指令或选项来控制此行为。这些内容通常在文档中定义。

我不相信这是正确的。C11 6.7.2.2规定:“枚举列表中的标识符被声明为具有int类型的常量,并且可以出现在任何允许这样的地方。”但也规定:“每个枚举类型都应与char、有符号整数类型或无符号整数类型兼容。类型的选择是实现定义的,但应能表示枚举成员的所有值。” - Lundin
对于您在IAR中的示例,这意味着Spade1、Spade2等被保证为(有符号)整数,但是枚举类型Cards的变量可能是char、有符号整数或无符号整数。 - Lundin
1
C11是无关紧要的,除非您正在使用实现它的编译器 - 目前很少有这样的编译器。所涉及的编译器符合ISO / IEC 9899:1999(根据文档)。此外,ISO标准可以说任何它想说的话; 我发布的文本实际上是IAR手册的屏幕截图 - 我没有编造它! - Clifford

2
如果你真的需要将数据大小保持在一个 char 中,那么你可以使用一组 #define 常量值来表示 enum 状态,并且只在赋值和测试中使用这些值。

2
对于符合标准的编译器,枚举常量始终是int类型(等同于signed int)。但是这些常量通常不会存储在内存中,因此它们的类型可能不会对内存需求产生太大影响。
声明为枚举类型的对象本身就是枚举类型,与char或某些带符号或无符号整数类型兼容。类型的选择是实现定义的(即编译器可以选择,但必须记录如何进行选择);唯一要求是该类型必须能够存储所有常量的值。
尽管令人难以置信,但常量的类型确实是int而不是枚举类型,但这就是语言的定义方式(原因是历史原因,C++有不同的规则)。
例如,给定以下代码:
enum foo { x, y, z };
enum foo obj;
obj = z;

表达式 z 的类型为 int,且其值为2(就像十进制常量2一样),但对象obj的类型为enum foo,具体大小取决于编译器,可能只有一个字节。赋值语句 obj = z; 包含从 intenum foo 的隐式转换(这种转换可能需要额外的代码)。

一些编译器可能提供一些非标准的方式来指定枚举类型的选择类型。有些甚至可能以某种方式违反标准。请参阅您编译器的文档,打印出 sizeof(enum foo) 的值,并在必要时检查生成的代码。

很可能您的编译器会在语言规定的限制下做出合理的决策。对于面向内存较少的嵌入式系统的编译器,特别是可能会选择较小的类型,或者让您指定一个。请查看您编译器的文档。

正如Ian的回答所示,如果您想要自己控制内存使用,可以使用charunsigned char对象。不过,您仍然可以使用enum定义来定义常量。例如:
enum { x, y, z }; // No tag, so you can't declare objects of this type
typedef unsigned char foo; // an enum_foo object is guaranteed to be 1 byte
foo obj = z;

参考资料:C语言标准的6.7.2.2节。此链接指向一个最近草案的2011年ISO C标准的1.7兆字节PDF文档;这个特定的章节自1989年以来没有发生重大变化。

这是 C 的正确答案。我可以验证标准文本在 C11 草案和官方 C11 标准之间没有改变。 - Lundin

1

是的,我知道,我只是希望有一种编译器开关可以改变这种默认行为。 - Flot2011
@Flot2011:这取决于你使用的编译器。你用的是哪个编译器? - Eric J.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接