我认为我根本不了解 enum
是什么以及何时使用它。
例如:
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
这里真正宣布的是什么?
这里声明了三件事:声明了一个匿名枚举类型,ShapeType
被声明为该匿名枚举的 typedef,三个名称 kCircle
、kRectangle
和 kOblateSpheroid
被声明为整数常量。
让我们分解一下。在最简单的情况下,可以将枚举声明为
enum tagname { ... };
这声明了一个带有标签 tagname
的枚举。在 C 和 Objective-C(但不是 C++)中,对这个 的任何引用都必须以 enum
关键字开头。例如:
enum tagname x; // declare x of type 'enum tagname'
tagname x; // ERROR in C/Objective-C, OK in C++
为了避免必须在任何地方使用 enum
关键字,可以创建 typedef:
enum tagname { ... };
typedef enum tagname tagname; // declare 'tagname' as a typedef for 'enum tagname'
这可以简化为一行:
typedef enum tagname { ... } tagname; // declare both 'enum tagname' and 'tagname'
最后,如果我们不需要能够将 enum tagname
与 enum
关键字一起使用,我们可以将 enum
设为匿名并仅使用 typedef 名称声明它:
typedef enum { ... } tagname;
现在,在这种情况下,我们将 ShapeType
声明为匿名枚举的类型定义名称。 ShapeType
实际上只是一个整数类型,并且只能用于声明包含声明中列出的值之一(即 kCircle
、kRectangle
和 kOblateSpheroid
之一)的变量。不过,您可以通过强制转换为 ShapeType
变量分配另一个值,因此在读取枚举值时必须小心。
最后,kCircle
、kRectangle
和 kOblateSpheroid
被声明为全局命名空间中的整数常量。由于没有指定具体值,它们被分配给从 0 开始的连续整数,因此 kCircle
为 0,kRectangle
为 1,kOblateSpheroid
为 2。
Apple 建议从 Xcode 4.4 开始定义这样的枚举:
typedef enum ShapeType : NSUInteger {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
它们还提供了一个方便的宏 NS_ENUM
:
typedef NS_ENUM(NSUInteger, ShapeType) {
kCircle,
kRectangle,
kOblateSpheroid
};
这些定义提供了更强大的类型检查和更好的代码完成。我找不到 NS_ENUM
的官方文档,但您可以观看来自 WWDC 2012 会议 here 的“现代 Objective-C”视频。
更新
官方文档链接here。
NS_ENUM
宏的解释:NSHipster.com/ns_enum-ns_options
枚举声明了一组有序值 - typedef 只是为其添加了一个方便的名称。第一个元素是 0 等等。
typedef enum {
Monday=1,
...
} WORKDAYS;
WORKDAYS today = Monday;
以上只是shapeType标签的枚举。
一种用户定义的类型,可能值为 kCircle
、kRectangle
或 kOblateSpheroid
。但是,枚举内部的值(kCircle 等)在枚举外部是可见的。记住这一点很重要(例如,int i = kCircle;
是有效的)。
64 位更改更新:根据 apple docs 关于 64 位更改,
枚举也有类型:在 LLVM 编译器中,枚举类型可以定义枚举的大小。这意味着某些枚举类型的大小也可能比您预期的要大。与所有其他情况一样,解决方案是不对数据类型的大小做出任何假设。相反,将任何枚举值分配给具有正确数据类型的变量
因此,如果您支持 64 位,则必须创建类型如下语法的枚举。
typedef NS_ENUM(NSUInteger, ShapeType) {
kCircle,
kRectangle,
kOblateSpheroid
};
或者
typedef enum ShapeType : NSUInteger {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
否则会导致警告为 Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType
快速编程更新:
很快,语法发生了变化。
enum ControlButtonID: NSUInteger {
case kCircle , kRectangle, kOblateSpheroid
}
enum(枚举的缩写)用于枚举一组值(枚举数)。值是由符号(一个词)表示的抽象事物。例如,一个基本的枚举可以是
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };
这个枚举被称为匿名,因为你没有一个符号来命名它。但这仍然是完全正确的。像这样使用它
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
好的。生活是美好的,一切都很顺利。但是有一天你需要重用这个枚举来定义一个新的变量来存储 myGrandFatherPantSize,然后你写:
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;
但是你有一个编译器错误“枚举器的重新定义”。实际上,问题在于编译器不确定您首先枚举并且您第二次描述相同的事物。
然后,如果您想在多个地方重用相同的枚举数集(此处为 xs...xxxxl),则必须使用唯一名称对其进行标记。第二次使用此设置时,您只需使用标签。但是不要忘记,这个标签不会替换枚举词,而只是替换枚举数的集合。然后照常注意使用枚举。像这样:
// Here the first use of my enum
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
// here the second use of my enum. It works now!
enum sizes myGrandFatherPantSize;
您也可以在参数定义中使用它:
// Observe that here, I still use the enum
- (void) buyANewDressToMyGrandMother:(enum sizes)theSize;
您可以说到处重写枚举并不方便,并且使代码看起来有点奇怪。你说的对。真正的类型会更好。
这是我们向峰会迈进的最后一步。通过添加一个 typedef 让我们将我们的枚举转换为一个真正的类型。哦,最后一件事,你的班级中不允许使用 typedef。然后在上面定义你的类型。像这样做:
// enum definition
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl };
typedef enum sizes size_type
@interface myClass {
...
size_type myGrandMotherDressSize, myGrandFatherPantSize;
...
}
请记住,标签是可选的。然后从这里开始,在这种情况下,我们不标记枚举器,而只是定义一个新类型。然后我们就不再需要它了。
// enum definition
typedef enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } size_type;
@interface myClass : NSObject {
...
size_type myGrandMotherDressSize, myGrandFatherPantSize;
...
}
@end
如果您使用 XCode 在 Objective-C 中进行开发,我会让您发现一些以 NS_ENUM 为前缀的不错的宏。这应该可以帮助您轻松地定义好的枚举,而且还可以帮助静态分析器在编译之前为您做一些有趣的检查。
好枚举!
typedef
对于重新定义现有变量类型的名称很有用。它提供短&调用数据类型的有意义的方式。例如:
typedef unsigned long int TWOWORDS;
在这里,unsigned long int 类型被重新定义为 TWOWORDS 类型。因此,我们现在可以通过编写声明 unsigned long int 类型的变量,
TWOWORDS var1, var2;
代替
unsigned long int var1, var2;
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
那么你可以像这样使用它:-
ShapeType shape;
和
enum {
kCircle,
kRectangle,
kOblateSpheroid
}
ShapeType;
现在你可以像这样使用它:-
enum ShapeType shape;
enum 用于为枚举元素分配值,这在 struct 中无法完成。所以每次我们可以通过分配给枚举变量的值来代替访问完整的变量。默认情况下,它以 0 赋值开始,但我们可以为它分配任何值,枚举中的下一个变量将被分配一个前一个值 +1 的值。
您可以使用以下格式,原始默认值从 0 开始,所以
kCircle 为 0,
kRectangle 为 1,
kOblateSpheroid 为 2。
您可以分配自己的特定起始值。
typedef enum : NSUInteger {
kCircle, // for your value; kCircle = 5, ...
kRectangle,
kOblateSpheroid
} ShapeType;
ShapeType circleShape = kCircle;
NSLog(@"%lu", (unsigned long) circleShape); // prints: 0
typedef 允许程序员将一种 Objective-C 类型定义为另一种。例如,
typedef int 计数器;将类型 Counter 定义为等效于 int 类型。这极大地提高了代码的可读性。
Typedef 是 C 和 C++ 中的关键字。它用于为基本数据类型(char、int、float、double、struct 和 enum)创建新名称。
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
在这里,它创建了枚举数据类型 ShapeType & 我们可以为枚举类型 ShapeType 编写新名称,如下所示
ShapeType shape1;
ShapeType shape2;
ShapeType shape3;
enum 可以减少许多类型的“错误”,并使代码更易于管理
#define STATE_GOOD 0
#define STATE_BAD 1
#define STATE_OTHER 2
int STATE = STATE_OTHER
该定义没有约束。这只是一个替代品。它不能限制状态的所有条件。当STATE赋值为5时,程序会出错,因为没有匹配的状态。但是编译器不会警告 STATE = 5
所以最好这样使用
typedef enum SampleState {
SampleStateGood = 0,
SampleStateBad,
SampleStateOther
} SampleState;
SampleState state = SampleStateGood;
不定期副业成功案例分享