7

我正在使用 Clang 的原始装箱功能将枚举成员打包到NSNumber

Clang 文档的Boxed Enums 部分对此表示编译器将枚举成员装箱为整数,除非指定了类型。

有趣的是,根据我将枚举成员传递给方法的方式,我得到不同大小的整数。我已经能够将案例隔离到以下代码

typedef enum _MyEnum {
    MyEnumMember1 = 1000
} MyEnum;

- (void)testEnumerationBoxing
{
    NSNumber *numberA = [self testA];
    NSNumber *numberB = [self testB:MyEnumMember1];

    CFNumberType numberTypeA = CFNumberGetType((__bridge CFNumberRef) numberA);
    CFNumberType numberTypeB = CFNumberGetType((__bridge CFNumberRef) numberB);
    NSLog(@"CF Number type for A: %lu; B: %lu", numberTypeA, numberTypeB);
}

- (NSNumber *)testA
{
    return @(MyEnumMember1);
}

- (NSNumber *)testB:(MyEnum)enumMember
{
    return @(enumMember);
}

控制台输出是

A 的 CF 编号类型:3;乙:4

(第一个是kCFNumberSInt32Type,第二个是kCFNumberSInt64Type

如果我将声明更改为,typedef enum _MyEnum : int我看到两者的结果相同:kCFNumberSInt32Type.

为什么两种装箱方法的整数大小不同?

4

2 回答 2

4

我认为这种情况在您提供的链接中有所描述:

对 enum 类型的值进行装箱会产生一个 NSNumber 指针,该指针具有根据 enum 的底层类型的创建方法,可以是固定的底层类型,也可以是编译器定义的整数类型,能够表示 enum 的所有成员的值枚举:

typedef enum : unsigned char { Red, Green, Blue } Color;
Color col => Red;
NSNumber *nsCol = @(col); // => [NSNumber numberWithUnsignedChar:]

但是图书馆中促销的细节没有涉及,这就是引入期望差异的地方。

-testA最终打电话+[NSNumber numberWithInt:]

-testB最终打电话+[NSNumber numberWithUnsignedInt:]

因此,您看到的抽象“提升”是因为CFNumber(因此NSNumber)此时实际上不支持无符号值(参见CFNumberType枚举常量)——根据您看到的输出,然后假设NSNumber实现只是提升到下一个有符号在构造函数的无符号初始化程序的情况下能够表示所有值的类型 - 显然没有测试该值以查看是否可以应用任何“宽度最小化”。

当然,NSNumber声明了将无符号类型作为参数的构造函数和初始化器,但无符号整数的内部表示实际上存储为有符号整数表示。

将装箱文字提升为NSNumber. 例如,uint16_t类型化的枚举将存储为 32 位 int(via numberWithUnsignedShort:),而 int32_t 也是 32 位 int(via numberWithInt:)。虽然在-testA值的情况下也是已知的,所以也可以在那里调用更合适的构造函数——所以编译器只是基于类型而不是类型和值来最小化宽度。当枚举的类型未指定或指定为无符号类型时,您可能会看到这样的促销活动。

于 2012-08-24T18:49:56.477 回答
1

枚举(enum)常量的一个问题是它们的数据类型经常是不确定的。换句话说,枚举常量是不可预测的 unsigned int。

看看http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Cocoa64BitGuide/64BitChangesCocoa/64BitChangesCocoa.html

我希望这有帮助!

于 2012-08-24T15:37:36.413 回答