26

我必须存储指令,我将通过串行接收的命令。命令的长度为 8 位。

我需要保持命令名称及其值之间的透明度。以避免必须将串行接收的 8 位数字转换为任何类型。

我想在我的代码中使用枚举来处理它们。在这个平台上,只有一个枚举对应一个 16 位整数。

该平台是 AVR ATmega169V 微控制器,在Butterfly 演示板上。它是一个 8 位系统,对 16 位操作的支持有限。它不是一个快速的系统,并且有大约 1KB 的 RAM。它没有文件 I/O 或操作系统之类的奢侈品。

那么关于我应该使用什么类型来存储 8 位命令有什么建议吗?
必须有比#defines 的大量标题更好的东西。

4

6 回答 6

41

gcc-fshort-enums可能有用:

仅将声明的可能值范围所需的字节数分配给“枚举”类型。具体来说,“枚举”类型将等效于具有足够空间的最小整数类型。

事实上,这里有一个包含很多相关信息的页面。我希望你能遇到许多你不知道存在的 GCC 开关。;)

于 2009-11-09T06:54:08.257 回答
8

您正在尝试解决一个不存在的问题。

您的问题被标记为 C。在 C 语言中,值上下文中的枚举类型与整数类型完全兼容,并且行为与其他整数类型一样。当在表达式中使用时,它们受到与其他整数类型完全相同的整数提升。考虑到这一点后,您应该意识到,如果要将枚举常量描述的值存储在 8 位整数类型中,您所要做的就是选择合适的通用 8 位整数类型(例如int8_t)并使用它而不是枚举类型。int8_t通过将枚举常量值存储在类型的对象中(与使用枚举类型显式声明的对象相反),您绝对不会失去任何东西。

您描述的问题将存在于 C++ 中,其中枚举类型与其他整数类型分离得更远。在 C++ 中,为了节省内存而使用整数类型代替枚举类型更加困难(尽管可能)。但不是在 C 中,它不需要任何额外的努力。

于 2010-02-27T07:57:46.163 回答
3

我不明白为什么枚举不起作用。与枚举的比较和分配都应该在默认扩展的情况下正常工作。请注意您的 8 位值已正确签名(我认为您需要无符号扩展名)。

您将通过这种方式获得 16 位比较,我希望这不会是性能问题(它不应该是,特别是如果您的处理器是 16 位的,因为它听起来像)。

于 2009-11-09T06:43:21.020 回答
2

微软的 C 编译器允许你做这样的事情,但它是一个扩展(它在 C++0x 中是标准的):

enum Foo : unsigned char {
    blah = 0,
    blargh = 1
};

由于您标记了 GCC,我不完全确定相同的事情是否可能,但 GCC 可能有一个扩展gnu99模式或其他东西。试一试。

于 2009-11-09T06:45:51.297 回答
0

出于以下原因,我建议在任何情况下都留在 enum 上:

  • 此解决方案允许您将命令值直接映射到您的串行协议所期望的值。
  • 如果您真的使用 16 位架构,那么迁移到 8 位类型并没有那么多优势。考虑保存 1 个内存字节以外的其他方面。
  • 在某些编译器中,我使用的实际枚举大小使用了最少的位数(可能适合字节的枚举仅使用字节,然后是 16 位,然后是 32 位)。

首先,您不应该关心实际类型的宽度。只有当你真的需要有效的存储方式时,你才应该在 GNU 编译器上使用编译器标志,例如 -fshort-enums,但我不推荐它们,除非你真的需要它们。

作为最后一个选项,您可以将“枚举”定义为命令的表示数据,并使用转换为字节的 2 个简单操作将命令值存储/恢复到内存/从内存中恢复(并将其封装在一个地方)。那这个呢?这些是非常简单的操作,因此您甚至可以内联它们(但这允许您真正使用 1 个字节进行存储,并从另一端使用您喜欢的最有用的枚举来执行操作。

于 2009-11-09T07:00:41.693 回答
0

与ARC 编译器相关的答案 (引自 DesignWare MetaWare C/C++ Programmer's Guide for ARC;第 11.2.9.2 节)

枚举大小 枚举类型的大小取决于切换 *Long_enums* 的状态。

■ 如果toggle *Long_enums* 关闭,则枚举类型映射到最小的一、二或四字节,以便可以表示所有值。

■ 如果切换*Long_enums* 处于打开状态,则枚举映射到四个字节(符合AT&T 便携式C 编译器约定)。

于 2014-03-05T11:57:47.643 回答