【问题标题】:Why are enums with negative values causing problems in Objective-C/C?为什么带有负值的枚举会在 Objective-C/C 中引起问题?
【发布时间】:2011-06-30 03:53:00
【问题描述】:

出于各种实施原因,我定义了以下枚举:

typedef enum HBSnakeMovementDirection
{
    HBSnakeMovementDirectionUp = 1,
    HBSnakeMovementDirectionDown = -1,
    HBSnakeMovementDirectionRight = 2,
    HBSnakeMovementDirectionLeft = -2
}
HBSnakeMovementDirection;

但是,如果我尝试使用 HBSnakeMovementDirectionRight,我会收到以下警告:

Implicit conversion changes signedness: 'int' to 'HBSnakeMovementDirection'

其他枚举值都没有问题。这里有什么问题?我认为这可能与混合负枚举值和正枚举值有关,但我找不到任何明确的信息。

(我能够提出所有积极的枚举值,让我能够解决这个问题,但它仍然难倒我,所以我想我会问一下。)

我应该声明,与我的所有项目一样,我启用了几乎所有警告——因此,-Wconversion 的投诉——并将它们视为错误。 (我喜欢在编译时尽可能严格。)我使用的是 LLVM 1.6。

更新 1:实际上任何使用 HBSnakeMovementDirectionRight 都会导致前面的警告:

HBSnakeMovementDirection movementDirectionRight = HBSnakeMovementDirectionRight;

我必须将 HBSnakeMovementDirectionRight 转换为 HBSnakeMovementDirection 以使警告静音。

更新 2:根据要求,这是在我的机器上发出的整个构建命令:

http://pastie.org/1580957

更新 3:这是我正在 GitHub 上托管的确切项目:

https://github.com/LucasTizma/Hebi

具体来说,如下树:

https://github.com/LucasTizma/Hebi/tree/89262e2e53881584daf029e3dd5f1e99dfbd6f96

【问题讨论】:

  • int 默认为 signedunsigned 是编译器特定的。因此,尝试使用接收参数为signed int 并检查。顺便说一句,显示一段您实际使用的代码。为什么声明和同义词在您的typedef 中具有相同的名称。虽然这不是问题,只是想知道。
  • @Mahesh, int 默认总是signed。您可能会想到char,它确实具有实现定义的签名。 @LucasTizma,您需要向我们展示您使用枚举值的地方的行和相关变量声明,以便我们为您提供帮助。
  • §6.7.2.2/2 和 C99 中的 /4 表示枚举常量(HBSnakeMovementDirectionRight)具有可表示为 int 的值,枚举类型(HBSnakeMovementDirection)应能够表示枚举的所有成员的值。所以,你的enum 类型似乎没有问题...
  • 尝试隔离最少量的代码来重现您的问题。 HBSnakeMovementDirection movementDirectionRight = HBSnakeMovementDirectionRight; printf("%d\n", movementDirectionRight); 使用 clang 1.6 和 GCC 4.2.1 编译并运行,没有任何警告。
  • 除了enum 中的标识符之外,还会有一些旧的、被遗忘的HBSnakeMovementDirectionRight 标识符吗?可能是#defineconst int

标签: objective-c c enums llvm signed


【解决方案1】:

正如 Darren 所说,它确实看起来像一个编译器错误,而 Dave 说 Clang 2.0 不会发生这种情况。

我发现以下类型定义使 OP 代码可以使用 Clang 1.6 编译:

typedef enum HBSnakeMovementDirection 
{
    HBSnakeMovementDirectionUp = 1,     // Default movement direction upon initialization via -init
    HBSnakeMovementDirectionDown = -1,
    HBSnakeMovementDirectionLeft = -2,
    HBSnakeMovementDirectionRight = 2,
    NBSnakeMovementDirectionNone = -3
}
HBSnakeMovementDirection;

(注意额外的NBSnakeMovementDirectionNone

这可能与 LLVM 错误 1884 有关,该错误已得到修复。

【讨论】:

  • 嗯,知道这与我的愚蠢无关,我感觉好多了。 :) 我计划最终切换到 LLVM 2.0,并且正如我在问题中指出的那样,我能够调整我的实现逻辑以使用非负枚举常量。非常感谢您的帮助!
【解决方案2】:

我可以重现这个。对我来说,它肯定看起来像一个编译器错误。枚举中存在负值会导致编译器错误地认为“2”的值超出了枚举的范围,因此会发出警告。

无论你指定“2”还是“HBSnakeMovementDirectionRight”,行为都是一样的:接受1,拒绝2。

编辑:我在现有的 iPhone 项目中对此进行了测试,设置了编译器 LLVM 1.6 并设置了 -Wconversion 标志。

typedef enum HBSnakeMovementDirection
{
    neg1 = -1,
    pos1 = 1,
    pos2 = 2,
} HBSnakeMovementDirection;

HBSnakeMovementDirection d = -3;  // Warning: Can't convert int to HBSnakeMovementDirection
HBSnakeMovementDirection d = -2;  // OK
HBSnakeMovementDirection d = -1;  // OK
HBSnakeMovementDirection d = 0;  // OK
HBSnakeMovementDirection d = 1;  // OK
HBSnakeMovementDirection d = 2;  // Warning: Can't convert int to HBSnakeMovementDirection
HBSnakeMovementDirection d = pos2;  // Warning: Can't convert int to HBSnakeMovementDirection

【讨论】:

  • 你能发布代码吗?我一直在尝试重现这个(不成功)大约 15 分钟。
  • @Dave DeLong:在我的问题中查看更新 3。我在 GitHub 上发布了我的确切项目。
【解决方案3】:

绝对看起来像一个编译器错误。我在 Xcode 3 中打开该项目并编译,并得到了错误。当我在 Xcode 4 中打开项目并使用 clang2.0 编译器时,我没有收到任何警告。

【讨论】:

    猜你喜欢
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多