我正在使用具有 32K 内存的嵌入式设备,使用 IAR EWARM v6.30 以纯 C 语言编写。
为了使代码更具可读性,我想定义一些枚举类型,例如,类似
{RIGHT_BUTTON, CENTER_BUTTON, LEFT_BUTTON}
而不是使用 0、1、2 值,但恐怕它会占用已经稀缺的额外内存。
所以我有两个问题:1)我可以强制枚举为短或字节类型而不是 int 吗?2)定义枚举类型的确切内存印记是什么?
在完全兼容的 ISO C 中,枚举常量的大小和类型是signed int
. 一些嵌入式系统编译器故意不将其作为优化或扩展来遵守。
在 ISO C++ 中“枚举的底层类型是一个整数类型,它可以表示枚举中定义的所有枚举值。 ”,因此编译器可以自由使用最小的可能类型,并且大多数都这样做,但没有义务这样做所以。
在您的情况下(IAR EWARM),手册明确指出:
不需要任何选项,实际上您需要使用它--enum_is_int
来强制遵守行为。其他编译器可能表现不同或具有不同的扩展、编译指示或选项来控制它。这些东西通常会在文档中定义。
如果您确实需要将数据大小保持在 a,char
那么您始终可以使用一组#define
常量值来表示enum
状态,并且只在您的作业和测试中使用这些值。
对于符合标准的编译器,枚举常量始终是类型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;
涉及从int
to的隐式转换enum foo
(该转换可能需要也可能不需要额外的代码)。
一些编译器可能会提供一些非标准的方式来指定要为枚举类型选择的类型。有些甚至可能以某种方式违反标准。查阅编译器的文档,打印出 的值sizeof (enum foo)
,并在必要时检查生成的代码。
您的编译器很可能会在语言强加的约束范围内做出合理的决定。对于针对内存不足的嵌入式系统的编译器,编译器特别有可能会选择一种小类型,或者让您指定一个。查阅编译器的文档。
正如伊恩的回答所暗示的,如果你想自己控制内存使用,你可以使用char
或unsigned 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 年以来,这一特定部分没有发生重大变化。
ANSI C 编译器将始终将枚举表示为int
以表示类型的变量enum
。
http://en.wikipedia.org/wiki/Enumerated_type#C_and_syntactically_similar_languages
在程序中使用 s 的一种选择int
是使用它们来定义值,但char
在实际使用时转换为
char value = (char)Buttons.RIGHT_BUTTON;