【问题标题】:Enumerated Type Value Not Comparing Correctly枚举类型值比较不正确
【发布时间】:2009-09-30 18:45:29
【问题描述】:

我正在为嵌入式应用程序编写一些 C 代码,但遇到了一个问题,其中与枚举值的比较没有正确执行。以如下代码sn-p为例:

typedef unsigned int UINT16;
typedef enum enum_items_tag
{
   ITEM_1,
   ITEM_2,
   ITEM_3,

   /* ... */

   ITEM_918,
   MAX_ENUM_ITEMS
} enum_items_t;

UINT16 n;

for ( n = 0; n < MAX_ENUM_ITEMS; n++ )
{
   // Do something
}

代码按预期执行,直到 n 增加到等于 MAX_ENUM_ITEMS,此时比较失败,并在循环内继续执行(当它应该退出时)。我过去做过这样的事情,没有任何问题。

我尝试将 n 重新键入为 enum_items_t(即将 n 声明为“enum_items_t n”),并将 MAX_ENUM_ITEMS 类型转换为 UINT16。此时我唯一能想到的另一件事是,我的枚举类型 (919) 中的项目数量可能存在问题。有谁知道枚举类型是否有这样的限制?我正在使用基于 GCC 的编译器。或者,如果您有任何其他想法,将不胜感激。谢谢。

【问题讨论】:

  • 您如何检查执行是否在循环内继续?
  • 当你说测试失败时,你是否真的添加了代码来确保它评估为假(例如if (n &lt; MAX...) {printf...}),或者你只是意味着它应该失败?
  • 是的,我已经对此做了很多调试,并单步执行了代码。我可以在我的调试器中观察 n 增加到与 MAX_ENUM_ITEMS (919) 相同的值,然后比较失败。不是跳出循环,而是在循环中继续执行。
  • 我会尝试使用不同版本的 gcc。我(曾经)遇到过编译器故障,导致执行流程进入非常奇怪的地方。
  • 您是否在编译时进行了优化?如果是这样,编译器可以看到循环内部和循环之后的某些代码位相似,并将它们围绕它们打乱;此时,调试器在尝试确定与当前指令对应的源代码行时会感到困惑,并且偶尔会显示 IP 在循环内执行一两条指令,而实际上它在其他地方。我不确定 g++,但我在 VC++ 和激进的优化设置中见过很多次。在这里查看的最好方法是printf

标签: c gcc enums compare


【解决方案1】:

这可能是一个错误吗?我希望 gcc 从 0 开始枚举......但你说你在调试时看到值增加到 919。所以这让我觉得要么你偶然在枚举中获得了一个额外的值,要么枚举值是基于 1 的,就像命名方案所暗示的那样。

如果 ITEM_1 == 1 则要么从 1 开始您的 n...,要么按如下方式更改 MAX_ENUM_ITEMS 的值:

typedef enum enum_items_tag
{
   ITEM_1,
   ITEM_2,
   ITEM_3,

   /* ... */

   ITEM_918,
   MAX_ENUM_ITEMS = ITEM_918
} enum_items_t;

【讨论】:

  • 好收获。要进行测试,请将ITEM_0 添加到枚举中。
  • 我很确定 GCC 从 0 开始枚举。我几乎相信这是一个标准,但我没有该标准的副本。这似乎是一种标准化的东西 - 它不会对实施产生巨大影响。
  • @Chris:在标准中(n1256.pdf中的6.7.2.2)“3 ...如果第一个枚举数没有=,则其枚举常数的值为0。 ... "
  • 是的,偏移量原来是问题所在。好收获!
【解决方案2】:

尝试使用 n = ITEM_1 开始循环?

【讨论】:

    【解决方案3】:

    ISO C 对 enums 的内部表示相当模糊,但它确实保证所使用的类型应该足够宽以处理所有值,只要您不超过 @987654322 的限制@。除非您使用某些编译器开关来启用特定于实现的行为,该行为将枚举表示设置为固定的东西(如char)。

    无论如何,尝试打印出sizeof(enum_items_t),看看你会得到什么。

    此外,int 每个 ISO C 至少应该是 16 位宽,但是在嵌入式平台(尤其是 DSP)上,您会遇到各种奇怪的事情,所以请检查 int 是否真的是 16 位,因为好吧。

    【讨论】:

    • 听起来不太像这个问题,因为它不是导致问题的“圆形”二进制数。老实说,这听起来更像是一个 gcc 错误。
    【解决方案4】:

    我会打印出 MAX_ENUM_ITEMS 只是为了确保它的值是您认为的值。有这么长的列表,不难搞砸。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-28
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-09
      • 1970-01-01
      相关资源
      最近更新 更多