关于指针的一些认知及困惑

指针

  • 变量的内存地址就是该变量的指针,而用于保存内存地址(指针)的变量就是指针变量

关于指针的2个基本的运算符:

  1. &:取地址运算符,用于读取后面变量的保存地址。是单目运算符,后面紧跟一个变量,
  2. *:取变量运算符,用于读取该指针变量所指的变量。单目运算符,后面紧跟一个指针变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
int main(int argc , char * argv[])
{
@autoreleasepool{
// 定义一个int型变量
int a = 200;
// 定义一个指向int变量的指针
int* p;
// 将a变量的指针(内存地址)赋值给p指针变量
p = &a;
// *p表示取出p指针所指变量
NSLog(@"%d" , *p);
// 对a变量先取指针,再获取该指针所指变量,又回到变量a,
// 因此下面代码将输出1(代表真)
NSLog(@"%d" , a == (*(&a)));
}
}
```
👌,我们开始问题:
### 正常情况下
```
int main(int argc, char * argv[]) {
@autoreleasepool {
int i = 0x1;
int* p = &i;
NSNumber *n = @(0xffff);
NSLog(@"%p",n);
NSString *d = @"d";
NSLog(@"%p",d);
NSString *s = @"s是短发啊啊啥的s是短发啊啊啥的s是短发啊啊啥的s是短发啊啊啥的s是短发啊啊啥的s是短发啊啊啥的";
NSLog(@"%p",s);
NSObject *obj = [[NSObject alloc]init];
NSLog(@"%p",obj);
NSLog(@"");
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

打印结果

1
2
3
4
2018-03-09 21:44:58.069869+0800 FaceRecoginizeDemo[81911:9244520] 0xb0000000000ffff2
2018-03-09 21:44:58.070636+0800 FaceRecoginizeDemo[81911:9244520] 0x10dc050d8
2018-03-09 21:44:58.071263+0800 FaceRecoginizeDemo[81911:9244520] 0x10dc050f8
2018-03-09 21:44:58.071951+0800 FaceRecoginizeDemo[81911:9244520] 0x60000000de60

我们知道打印指针,LLDB中应该返回该指针存储的对象的地址,比如:

1
2
3
4
5
(lldb) po p
0x00007ffee1ffc01c
(lldb) po obj
<NSObject: 0x60000000de60>

NSNumber

其中对于指向NSNumber对象的指针n,由于 Tagged Pointer 机制,直接存储在指针本身中,故而在64位架构中NSNumber 成了一个没有 isa 假的对象;

1
2
3
4
5
6
//NSLog(@"%p",n);
2018-03-09 21:44:58.069869+0800 FaceRecoginizeDemo[81911:9244520] 0xb0000000000ffff2
(lldb) po n->isa
error: Couldn't apply expression side effects : Couldn't dematerialize a result variable: couldn't read its memory
(lldb)

故而,会出现,当我们想真正打印指针p中存储的地址的时候–不显示地址,打印指针地址直接显示NSNumber数值的状况(我也只能这么向自己解释了):

1
2
(lldb) po *p
1

NSString + 困惑

但是,对于指向字符串类型的指针,我却无法解释:

1
2
3
4
5
(lldb) po d
d
(lldb) po s
s是短发啊啊啥的s是短发啊啊啥的s是短发啊啊啥的s是短发啊啊啥的s是短发啊啊啥的s是短发啊啊啥的

也是没有打印地址!直接显示对象的值!

1
2
2018-03-09 21:44:58.070636+0800 FaceRecoginizeDemo[81911:9244520] 0x10dc050d8
2018-03-09 21:44:58.071263+0800 FaceRecoginizeDemo[81911:9244520] 0x10dc050f8

显然,一个占8个字节指针也是放不下这么多字符串的.
而且,为什么,*号后面➕指针,只能打印出基本数据类型呢?

1
2
3
4
5
6
7
8
9
(lldb) po *p
1
(lldb) po *n
error: Couldn't apply expression side effects : Couldn't dematerialize a result variable: couldn't read its memory
(lldb) po *s
(lldb) po *d
(lldb) po *obj

除了指向整型的指针,指向对象的指针无法通过*object获取该对象本身都?

什么鬼?
???
??


答案:

最近看了一篇关于LLDB的文章–认识Xcode中的重要成员:lldb调试器—-引用的原文,其中讲到:

在OC里所有的对象都是用指针表示的,所以一般用p、print、call、expression –打印的时候,打印出来的是对象的指针,而不是对象本身。如果我们想打印对象。我们需要使用命令选项:-O。为了更方便的使用,lldb为expression -O –定义了一个别名:po

————原来po打印的是对象,p打印的是指针!!

NiHong wechat
欢迎扫码,愿结识志同道合的朋友...