以基本數(shù)據(jù)類型、引用類型、數(shù)組為例分析指針偏移的過程
1、&和*的理解
&和* 是兩種指針運(yùn)算符,&是取地址運(yùn)算符,得到操作數(shù)的內(nèi)存地址,取出內(nèi)存地址功能,比如i 是一個(gè)int變量,則&i是這個(gè)i的地址。 *是間接尋址運(yùn)算符,返回操作數(shù)所指定地址的變量的值。
代碼:
/*
&是取地址運(yùn)算符
*是間接尋址運(yùn)算符
*/
void test11(){
int a = 1;
int *b = &a;
int c = *b;
NSLog(@"wenyi--a:%d,b:%p,c:%d",a,b,c);
}
2、基本數(shù)據(jù)類型
代碼:
void baseDataTypeTest(){
int a = 9;
int b = 10;
int *f = &a;
NSLog(@"基本數(shù)據(jù)類型的變量a:%d -- 變量地址:%p",a,&a);
NSLog(@"基本數(shù)據(jù)類型的變量b:%d -- 變量地址:%p",b,&b);
NSLog(@"基本數(shù)據(jù)類型的指針a:%p -- 指針b:%p",f,f-1);
NSLog(@"指針變量f所指向的a變量的內(nèi)容:%d -- 變量b的內(nèi)容:%d",*f,*(f-1));
NSLog(@"指針變量f所在的內(nèi)存地址:%p",&f);
}
運(yùn)行結(jié)果:
基本數(shù)據(jù)類型
結(jié)果:
2021-10-12 12:29:14.880387+0800 指針偏移[70684:2791244] 基本數(shù)據(jù)類型的變量a:9 -- 變量地址:0x1040bb2bc
2021-10-12 12:29:14.880773+0800 指針偏移[70684:2791244] 基本數(shù)據(jù)類型的變量b:10 -- 變量地址:0x1040bb2b8
2021-10-12 12:29:14.880818+0800 指針偏移[70684:2791244] 基本數(shù)據(jù)類型的指針a:0x1040bb2bc -- 指針b:0x1040bb2b8
2021-10-12 12:29:14.880848+0800 指針偏移[70684:2791244] 指針變量f所指向的a變量的內(nèi)容:9 -- 變量b的內(nèi)容:10
2021-10-12 12:29:14.880872+0800 指針偏移[70684:2791244] 指針變量f所在的內(nèi)存地址:0x1040bb2b0
分析:
- 1、基本數(shù)據(jù)類型存儲(chǔ)在棧中,因此直接將10數(shù)值存儲(chǔ)在棧中
- 2、棧的存儲(chǔ)方式是從高地址到低地址,所以變量a的地址值比變量b的地址值要高
- 3、因?yàn)轭愋蜑閕nt型,a占有4個(gè)字節(jié),所以b地址比a地址低了4個(gè)字節(jié)
- 4、&a是將變量a的地址取出來
- 5、int *f = &a是將變量a的地址賦值到指針變量e上
- 6、打印f和f-1可以看到分別打印的是a和b的地址,也可以證明指針變量存儲(chǔ)的就是地址
- 7、為什么是f-1,而不是f+1,這是因?yàn)闂5拇鎯?chǔ)方式是從高地址到低地址,所以得到b的指針需要通過f-1
- 8、*f是對(duì)指針變量使用 *,可以得到指針變量存儲(chǔ)的地址所存儲(chǔ)的內(nèi)容,因此 * f, *(f-1)分別到的a和b變量的內(nèi)容
- 9、也可以對(duì)指針變量f取地址,取到的地址就是指針變量的地址,被b地址小了8個(gè)字節(jié)
圖示:

基本數(shù)據(jù)類型的指針偏移.png
3、引用類型
代碼:
void quoteTest(){
NSperson *person1 = [NSperson alloc];
NSperson *person2 = [NSperson alloc];
NSLog(@"引用類型的指針person1:%@ -- 變量地址:%p",person1,&person1);
NSLog(@"引用類型的指針person2:%@ -- 變量地址:%p",person2,&person2);
}
運(yùn)行結(jié)果:
引用類型
指針是8個(gè)字節(jié),所以相差8個(gè)字節(jié)
結(jié)果:
2021-10-12 12:29:14.881025+0800 指針偏移[70684:2791244] 引用類型的指針person1:<NSperson: 0x105014c50> -- 變量地址:0x1040bb2b8
2021-10-12 12:29:14.881069+0800 指針偏移[70684:2791244] 引用類型的指針person2:<NSperson: 0x105013d90> -- 變量地址:0x1040bb2b0
分析:
- 指針是在棧中,對(duì)象是在堆中
- 一個(gè)指針占8個(gè)字節(jié),所以指針按地址空間來說&p1和&p2二者之間相差8個(gè)字節(jié)
- 而指針本身是緊挨著的,也就是說&p1的下一個(gè)指針就是&p2
圖示:

引用類型的指針偏移.png
4、數(shù)組類型
代碼:
void arrayTest(){
int a = 10;
int aa = 12;
int c[4] = {1,2,3,4};
int b = 20;
int *d = c;
NSLog(@"數(shù)組所在地址:%p -- 數(shù)組首元素地址:%p -- 數(shù)組第二元素地址:%p",&c,&c[0],&c[1]);
NSLog(@"數(shù)組所在地址:%p -- 數(shù)組第二元素地址:%p -- 數(shù)組第三元素地址:%p",d,d+1,d+2);
NSLog(@"數(shù)組第一個(gè)元素:%d -- 數(shù)組第二元素地址:%d -- 數(shù)組第三元素地址:%d",*d,*(d+1),*(d+2));
NSLog(@"基本數(shù)據(jù)類型a:%p -- 基本數(shù)據(jù)類型b:%p -- aa:%p",&a,&b,&aa);
}
運(yùn)行結(jié)果:
結(jié)果:
2021-10-12 12:29:14.881097+0800 指針偏移[70684:2791244] 數(shù)組所在地址:0x1040bb2a0 -- 數(shù)組首元素地址:0x1040bb2a0 -- 數(shù)組第二元素地址:0x1040bb2a4
2021-10-12 12:29:14.881122+0800 指針偏移[70684:2791244] 數(shù)組所在地址:0x1040bb2a0 -- 數(shù)組第二元素地址:0x1040bb2a4 -- 數(shù)組第三元素地址:0x1040bb2a8
2021-10-12 12:29:14.900159+0800 指針偏移[70684:2791244] 數(shù)組第一個(gè)元素:1 -- 數(shù)組第二元素地址:2 -- 數(shù)組第三元素地址:3
分析:
- 數(shù)組名不是指針
- &c是獲取數(shù)組的空間地址,&c[0]是獲取數(shù)組的第一個(gè)數(shù)據(jù)的空間地址,他們兩個(gè)是一個(gè)地址
- 因?yàn)閿?shù)據(jù)是int型,每個(gè)數(shù)據(jù)占用4個(gè)字節(jié),所以數(shù)據(jù)的地址都相隔四個(gè)字節(jié),而指針本身是緊挨著的
- d獲取的是數(shù)組的指針,d+1是&c[1]地址空間的指針,指針的+1就會(huì)走到下個(gè)指針,我們可以通過指針的偏移來獲取數(shù)據(jù),下一個(gè)指針就是下一個(gè)數(shù)據(jù)的地址空間。
- 數(shù)組的數(shù)據(jù)從前到后順序存儲(chǔ),而不是從后到前
圖示:

數(shù)組的指針偏移.png