为什么带有负值的枚举会导致Objective-C/C中出现问题?
出于各种实现原因,我定义了以下枚举:为什么带有负值的枚举会导致Objective-C/C中出现问题?,objective-c,c,enums,llvm,signed,Objective C,C,Enums,Llvm,Signed,出于各种实现原因,我定义了以下枚举: typedef enum HBSnakeMovementDirection { HBSnakeMovementDirectionUp = 1, HBSnakeMovementDirectionDown = -1, HBSnakeMovementDirectionRight = 2, HBSnakeMovementDirectionLeft = -2 } HBSnakeMovementDirection; 但是,如果我尝试使用
typedef enum HBSnakeMovementDirection
{
HBSnakeMovementDirectionUp = 1,
HBSnakeMovementDirectionDown = -1,
HBSnakeMovementDirectionRight = 2,
HBSnakeMovementDirectionLeft = -2
}
HBSnakeMovementDirection;
但是,如果我尝试使用HBSnakeMovementDirectionRight
,我会收到以下警告:
HBSnakeMovementDirection movementDirectionRight = HBSnakeMovementDirectionRight;
隐式转换将符号:“int”更改为“HBSnakeMovementDirection”
它与任何其他枚举值都没有问题。这里有什么问题?我认为这可能与混合负枚举值和正枚举值有关,但我找不到任何明确的信息
(我能想出所有的正枚举值来解决这个问题,但它仍然难住了我,所以我想我应该问一下。)
我应该声明,与我所有的项目一样,我启用了几乎所有的警告,因此,-Wconversion
的投诉,并将其视为错误。(我喜欢在编译时尽可能严格。)我使用的是LLVM1.6
更新1:任何使用HBSnakeMovementDirectionRight
的行为都会导致前面的警告:
HBSnakeMovementDirection movementDirectionRight = HBSnakeMovementDirectionRight;
我必须将HBSnakeMovementDirectionRight
转换为HBSnakeMovementDirection
以使警告静音
更新2:根据请求,以下是在我的计算机上发出的整个生成命令:
更新3:以下是我在GitHub上主持的确切项目:
具体而言,以下树:
我可以复制这个。在我看来,它确实像一个编译器bug。枚举中出现负值会导致编译器错误地认为“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
看起来确实像个编译器错误。我在Xcode 3中打开了这个项目并进行了编译,得到了错误。当我在Xcode 4中打开项目并使用clang2.0编译器时,我没有收到任何警告。正如Darren所说,它看起来确实像一个编译器错误,Dave说clang2.0不会出现这种情况 我发现以下类型定义使操作代码以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错误有关,该错误已被修复。
int
默认为signed
或unsigned
是特定于编译器的。因此,尝试使用接收参数signed int
并进行检查。顺便说一句,展示一段你实际使用的代码。为什么声明和同义词在typedef
中具有相同的名称。虽然这不是问题,只是好奇地想知道。@Mahesh,int
在默认情况下总是有符号的。您可能会想到char
,它确实具有实现定义的签名@LucasTizma,您需要向我们展示使用枚举值的位置的行和相关变量声明,以便我们为您提供帮助。§C99中的§6.7.2.2/2和/4说明枚举常量(HBSnakeMovementDirectionRight
)有一个可表示为int
)的值和枚举类型(HBSnakeMovementDirection
)应能够表示枚举的所有成员的值。因此,您的enum
类型中似乎没有问题…请尝试隔离再现问题的最小代码量。HBSnakeMovementDirection movementDirectionRight=HBSnakeMovementDirectionRight;printf(“%d\n”,movementDirectionRight)
编译并运行时没有任何警告,使用的是clang 1.6和GCC 4.2.1。除了枚举中的标识符之外,还会有一些旧的、被遗忘的HBSnakeMovementDirectionRight
标识符吗?可能是#define
或const int
。你能发布代码吗?我一直在尝试重新编写这个代码(未成功)大约15分钟。@Dave DeLong:查看我问题中的更新3。我在GitHub上发布了我的确切项目。知道这与我的愚蠢无关,我感觉好多了。:)我计划最终切换到LLVM 2.0,正如我在问题中指出的那样,我能够调整我的实现逻辑以处理非负枚举常量。非常感谢您的帮助!