为什么cocoa到处都没有使用相同的枚举声明风格?

时间:2010-02-11 18:19:28

标签: objective-c cocoa nsinteger nsuinteger

我想知道可可的不同风格的枚举宣言背后的理由是什么?

像这样:

enum { constants.. }; typedef NSUInteger sometype;

是否有理由使用typedef来获取NSUInteger的分配而不进行强制转换?

有时typedef是NSInteger / NSUInteger,为什么不总是使用NSInteger?使用NSUInteger有真正的好处吗?

有时会使用枚举标记名,例如_NSByteOrder上的here

这个答案也很有用:What is a typedef enum in Objective-C?

3 个答案:

答案 0 :(得分:12)

有几个原因:

原因1:灵活性:

enum lickahoctor { yes = 0, no = 1, maybe = 2 };

声明一个枚举。您可以在任意位置使用值yesnomaybe,并将它们分配给任何整数类型。您也可以通过编写

将其用作类型
enum lickahoctor myVar = yes;

这很好,因为如果一个函数采用enum lickahoctor类型的参数,你就会知道你可以为它分配yesnomaybe。此外,调试器将知道,因此它将显示符号名称而不是数值。麻烦的是,编译器只允许您将enum lickahoctor中定义的值分配给myVar。例如,如果您想在基类中定义一些标志,那么在子类中添加一些标志,就不能这样做。

如果您使用int,则不会出现此问题。所以你想使用某种int,所以你可以分配任意常量。

原因2:二进制兼容性:

编译器选择一个适合你在枚举中定义的所有常量的大小。无法保证你会得到什么。因此,如果您将包含此类变量的结构直接写入文件,则无法保证在您使用下一版本的应用程序将其重新读入时它仍然具有相同的大小(根据C标准,至少 - - 在实践中并不是那么黯淡。)

如果您使用某种int,平台通常会保证该数字的特定大小。特别是如果您使用其中一种保证为特定尺寸的类型,例如int32_t / uint32_t

原因3:可读性和自我记录

当您在上面声明myVar时,您可以立即明白其中的值。如果您只使用int或uint32_t,则不是。所以你要做的就是使用

enum { yes, no, maybe };
typedef uint32_t lickahoctor;

为常量附近的某个定义一个很好的名称,它会提醒人们这种类型的变量可以保存这个值。但是,如果需要,您仍然可以获得可预测的固定大小以及在子类中定义其他值的能力。

原因4:支持位域

枚举类型变量仅支持从其选项中精确分配一个值。因此,如果您尝试实现位字段,则无法将其键入为位域。此外,您需要使用无符号变量来避免符号扩展使您无法使用。

答案 1 :(得分:2)

  

是否使用typedef获取的原因   NSUInteger的工作分配   没有铸造?

typedef用于指定枚举值的基本类型。只要您通过强制转换为较小的类型(NSUIntegerunsigned short)截断值,就可以将枚举值强制转换为其他类型。

通过为有符号和无符号整数提供架构/平台无关类型,引入了

NSIntegerNSUInteger以简化应用程序的64位迁移。这样,无论CPU有多少位,都不需要重写应用程序。

  

有时typedef是   NSInteger / NSUInteger,为什么不使用   NSInteger总是?真的有吗?   使用NSUInteger获益?

选择取决于枚举中的值。有些枚举有很多值,所以它们需要所有可用的位:

  • NSInteger提供2 ^ 31个正负值(32位架构)。
  • NSUInteger提供2 ^ 32个正值(32位架构)。
  • 如果枚举仅包含正值,则使用NSUInteger。
  • 如果枚举是包含正值和负值,则使用NSInteger。
  • NSUInteger通常用于标志枚举,因为它提供了32个不同的值(在32位架构上),可随意组合。

我不知道Apple开发团队是否有选择规则。我希望如此......

答案 2 :(得分:1)

虽然你可以使用像

这样的东西
  typedef enum { constants... } sometype;

无法保证数据类型的最终比特大小。嗯,这不是严格意义上的,但它足够真实。它更适合在具体数据大小中定义API,而不是根据所使用的编译器设置而改变的内容。