为什么 Objective C 对象的 isa 字段与其 class 指针有 1 个偏移量?

Why is isa field of Objective C object has 1 offset with its class pointer?

我正在尝试使用以下代码来理解 NSObject 的 C 结构布局。首先我使用 NSData 打印它的结构布局,然后我直接使用 [NSObject class].

打印 class 指针
id obj = [NSObject new];
long nsSize = class_getInstanceSize([NSObject class]);
NSData *nsData = [NSData dataWithBytes:(__bridge const void *)obj length:nsSize];
NSLog(@"obj: %@", nsData);
NSLog(@"NSObject Class: %p", [NSObject class]);

我得到了结果:

2015-10-15 08:11:53.913 ObjC_CMD[11406:1999149] obj: <f1e06573 ffff1d00>
2015-10-15 08:11:53.913 ObjC_CMD[11406:1999149] NSObject Class: 0x7fff7365e0f0

有趣的是class指针的结尾是e0f0,而NSData打印结果显示它的isa是eof1(由于小端字节序,顺序相反)。我在书中读到 isa 指针在对象的结构布局中最顶层,那么为什么它有 1 个偏移量?

顺便说一句,我也尝试过其他类型的对象,在isa和class指针之间总是有1个偏移量。他们不应该是一样的吗?

P.S。 刚注意到class指针是0x7fff开头的,而C结构中的isa好像是0xffff,这个区别也很有意思。 isa 字段和从 [NSObject class] 获得的 class 指针之间的确切关系是什么?

The 1 in the least significant bit means isa is not a pointer. In 64-bit land, the 64-bits of isa got repurposed 转换为位掩码。 isa 位掩码最重要的一侧是其他位字段和引用计数。

部分 isa 位掩码(中间 30 位)标识 class 对象,这是您识别的部分。