我正在阅读一个iPhone示例项目的代码(Xcode IDE, Apple LLVM编译器4.2)。在iPhone样例项目的外部库(用C编写)的头文件中,有一些事件声明为枚举类型:
typedef enum _Application_Events
{
EVENT_EXIT = 0x80000000,
EVENT_TOUCH,
EVENT_DRAG,
EVENT_RELEASE_TOUCH,
EVENT_ROTATE_0,
EVENT_ROTATE_90,
EVENT_ROTATE_180,
EVENT_ROTATE_270
} Application_Events;
我不明白这些事件被赋予了什么样的值。0x80000000
应该是一个大的正整数(2147483648
),还是负零,还是负整数(-2147483648
)?
我在Xcode调试器中检查,编译器为Apple LLVM compiler 4.2, EVENT_EXIT
= (int) -2147483648
, EVENT_RELEASE_TOUCH
= (int) -2147483645
等。
显然,它们被处理在2的补表示中。相关文章可以在这里找到。
但我现在不确定的是:
(1) 0x80000000
的底层数据类型总是int
或其他情况下的其他东西?这取决于编译器还是平台?
(2)如果我将十六进制值分配给这样的有符号整数,它是否总是被解释为两个的补码表示?这取决于编译器还是平台?相关文章可以在这里找到。另一个参考可以在这里找到。
请分享一些想法。D
和许多类c语言一样,枚举只是一个整数。像这样设置第一个值将导致编译器从那里开始自增,从而保证所有枚举值都小于0。(作为一个有符号整数的2s恭维,被设置的高位将表示一个负数)
很可能,程序员选择这个值是为了能够发送各种类型的事件,并且不应该与其他值冲突。
简而言之,不要担心实际值;它只是一个数字。使用名称并理解它在使用或返回这些代码的调用上下文中的含义。
枚举的基类型是实现定义的。在这种情况下,基类型应该是unsigned int
,因为标准要求编译器选择一个足够宽的基类型来容纳所有枚举值。来自C99标准,6.7.2.2.4节:
每个枚举类型必须与
char
、有符号整数类型或无符号整数类型兼容。类型的选择是由实现定义的,108),但必须能够表示枚举的所有成员的值。在}
结束枚举器声明列表之前,枚举类型是不完整的。108)一个实现可能会延迟整数类型的选择,直到所有枚举常量都被看到。
- 枚举的类型是int。
- 0x80000000只是一个数字,但采用十六进制表示法。它的值是您在调试器(或任何十六进制到十进制转换器)中确认的值。
- 枚举的工作方式是从任何显式赋值的值中增量地赋值。因此,在这种情况下,枚举被分配为EVENT_EXIT=0x80000000, EVENT_TOUCH=0x80000001, EVENT_DRAG=0x80000002,等等。
enum
的底层类型取决于它需要保存的值。编译器在如何最终定义该类型上有一定的自由度。在您的例子中,Application_Events
的底层类型很可能是unsigned int
,因为它大于INT_MAX
,假设int
的大小是32位(enum
通常是32位)。比如:
enum foo_t {
FOO_Start,
FOO_Thing,
FOO_Another_Thing,
FOO_End
};
enum foo_t
的类型可以是int
或unsigned int
。
但是,枚举常量(如EVENT_EXIT
、FOO_Start
等)的类型为int
。这就是你在调试器中看到的。如果你输入
Application_Events foo = EVENT_EXIT;
foo
的类型可以是unsigned
。我觉得这个问题有点变化,所以:
1)对于iPhone来说,常量0x80000000
可能是unsigned
(iPhone ARM处理器有32位int
s),它的值取决于平台和使用的C版本。
2)对于实际情况,您可以假设您的处理器将支持2的补码算法,因为大多数平台都使用它。然而,C语言本身并不保证。其他算术格式(1的补码,有符号的大小)也是允许的。