I'm trying to using the following code to understand NSObject's C struct layout. First I print its struct layout using NSData, then I print the class pointer directly using [NSObject 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]);
And I got the result:
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
What's interesting is the end of class pointer is e0f0, while the NSData
print result shows its isa as eof1 (it's in reverse order because of little endian). I read in book that the isa pointer is topmost in an object's struct layout, so why it has 1 offset?
By the way, I have also tried on other types of objects, there is always 1 offset between isa and class pointer. Shouldn't they be the same?
P.S.
I just noticed that the class pointer begins with 0x7fff, but the isa in C struct seems to be 0xffff, this difference is also interesting. What's the exact relationship between isa field and class pointer obtained from [NSObject 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 into a bit-mask. On the most significant side of the isa
bit-mask are other bit fields and the reference count.
Part of the isa
bit-mask (30 bits in the middle) identify the class object, which is the part you recognized.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With