在新的系统中,我们打印NSNumber
、NSString
这些小数据的地址时,发现打印结果并不是我们想象中的Tagged Pinter
,这是因为苹果为了安全起见,对Tagged Pinter
存储时进行了一次编码操作,编码后的结果看起来像普通对象的指针。编码需要用到一个全局变量objc_debug_taggedpointer_obfuscator
,这个全局变量初始化时是随机生成的,用这个全局变量和Tagged Pinter
进行按位异或运算就得到了编码的结果。我们想要得到正确的Tagged Pinter
,就要再进行一次解码操作,解码就是用编码的结果和objc_debug_taggedpointer_obfuscator
再进行一次异或运算(一个数和任何一个数进行2次异或运算结果还是它本身,也就是a^b^b==a
)。
- (void)taggedPointerTest{
int a = 1;
NSInteger b = 2;
CGFloat c = 3;
double d = 4;
NSNumber *intN = @(a);
NSNumber *integerN = @(b);
NSNumber *cgfloatN = @(c);
NSNumber *doubleN = @(d);
NSString *string = [NSString stringWithFormat:@"abc"]; // 注意不能直接将@"abc"赋值给string
NSLog(@"intN--%p--0x%lx",intN,_objc_decodeTaggedPointer_(intN));
NSLog(@"integerN--%p--0x%lx",integerN,_objc_decodeTaggedPointer_(integerN));
NSLog(@"cgfloatN--%p--0x%lx",cgfloatN,_objc_decodeTaggedPointer_(cgfloatN));
NSLog(@"doubleN--%p--0x%lx",doubleN,_objc_decodeTaggedPointer_(doubleN));
NSLog(@"string--%p--0x%lx",string,_objc_decodeTaggedPointer_(string));
}
// objc_debug_taggedpointer_obfuscator是一个全局变量,这里
extern uintptr_t objc_debug_taggedpointer_obfuscator;
uintptr_t _objc_decodeTaggedPointer_(id ptr){ // 这是苹果源码中的解码函数
return (uintptr_t)ptr ^ objc_debug_taggedpointer_obfuscator;
}
********************************输出结果********************************
2019-12-03 09:55:34.424407+0800 NetTest[22806:9654578] intN--0xb54a89079699c2de--0xb000000000000012
2019-12-03 09:55:34.424583+0800 NetTest[22806:9654578] integerN--0xb54a89079699c2ef--0xb000000000000023
2019-12-03 09:55:34.424703+0800 NetTest[22806:9654578] cgfloatN--0xb54a89079699c2f9--0xb000000000000035
2019-12-03 09:55:34.424804+0800 NetTest[22806:9654578] doubleN--0xb54a89079699c289--0xb000000000000045
2019-12-03 09:55:34.424879+0800 NetTest[22806:9654578] string--0xa54a890790afe4df--0xa000000006362613
网友评论