指针偏移的认识

OC底层原理探索文档汇总

以基本数据类型、引用类型、数组为例分析指针偏移的过程

1、&和*的理解

&和* 是两种指针运算符,&是取地址运算符,得到操作数的内存地址,取出内存地址功能,比如i 是一个int变量,则&i是这个i的地址。 *是间接寻址运算符,返回操作数所指定地址的变量的值。

代码:

/*
 &是取地址运算符
 *是间接寻址运算符
 */
void test11(){
    int a = 1;
    int *b = &a;
    int c = *b;
    
    NSLog(@"wenyi--a:%d,b:%p,c:%d",a,b,c);
}

2、基本数据类型

代码:

void baseDataTypeTest(){
    int a = 9;
    int b = 10;
    int *f = &a;
    
    NSLog(@"基本数据类型的变量a:%d -- 变量地址:%p",a,&a);
    NSLog(@"基本数据类型的变量b:%d -- 变量地址:%p",b,&b);
    NSLog(@"基本数据类型的指针a:%p -- 指针b:%p",f,f-1);
    NSLog(@"指针变量f所指向的a变量的内容:%d -- 变量b的内容:%d",*f,*(f-1));
    NSLog(@"指针变量f所在的内存地址:%p",&f);
}

运行结果:

基本数据类型
 
 结果:
 2021-10-12 12:29:14.880387+0800 指针偏移[70684:2791244] 基本数据类型的变量a:9 -- 变量地址:0x1040bb2bc
 2021-10-12 12:29:14.880773+0800 指针偏移[70684:2791244] 基本数据类型的变量b:10 -- 变量地址:0x1040bb2b8
 2021-10-12 12:29:14.880818+0800 指针偏移[70684:2791244] 基本数据类型的指针a:0x1040bb2bc -- 指针b:0x1040bb2b8
 2021-10-12 12:29:14.880848+0800 指针偏移[70684:2791244] 指针变量f所指向的a变量的内容:9 -- 变量b的内容:10
 2021-10-12 12:29:14.880872+0800 指针偏移[70684:2791244] 指针变量f所在的内存地址:0x1040bb2b0

分析:

  • 1、基本数据类型存储在栈中,因此直接将10数值存储在栈中
  • 2、栈的存储方式是从高地址到低地址,所以变量a的地址值比变量b的地址值要高
  • 3、因为类型为int型,a占有4个字节,所以b地址比a地址低了4个字节
  • 4、&a是将变量a的地址取出来
  • 5、int *f = &a是将变量a的地址赋值到指针变量e上
  • 6、打印f和f-1可以看到分别打印的是a和b的地址,也可以证明指针变量存储的就是地址
  • 7、为什么是f-1,而不是f+1,这是因为栈的存储方式是从高地址到低地址,所以得到b的指针需要通过f-1
  • 8、*f是对指针变量使用 *,可以得到指针变量存储的地址所存储的内容,因此 * f, *(f-1)分别到的a和b变量的内容
  • 9、也可以对指针变量f取地址,取到的地址就是指针变量的地址,被b地址小了8个字节

图示:

基本数据类型的指针偏移.png

3、引用类型

代码:

void quoteTest(){
    NSperson *person1 = [NSperson alloc];
    NSperson *person2 = [NSperson alloc];
    NSLog(@"引用类型的指针person1:%@ -- 变量地址:%p",person1,&person1);
    NSLog(@"引用类型的指针person2:%@ -- 变量地址:%p",person2,&person2);
}

运行结果:

引用类型
 指针是8个字节,所以相差8个字节
 
 结果:
 2021-10-12 12:29:14.881025+0800 指针偏移[70684:2791244] 引用类型的指针person1: -- 变量地址:0x1040bb2b8
 2021-10-12 12:29:14.881069+0800 指针偏移[70684:2791244] 引用类型的指针person2: -- 变量地址:0x1040bb2b0

分析:

  • 指针是在栈中,对象是在堆中
  • 一个指针占8个字节,所以指针按地址空间来说&p1和&p2二者之间相差8个字节
  • 而指针本身是紧挨着的,也就是说&p1的下一个指针就是&p2

图示:

引用类型的指针偏移.png

4、数组类型

代码:

void arrayTest(){
    int a = 10;
    int aa = 12;
    int c[4] = {1,2,3,4};
    int b = 20;
    int *d = c;
    NSLog(@"数组所在地址:%p -- 数组首元素地址:%p -- 数组第二元素地址:%p",&c,&c[0],&c[1]);
    NSLog(@"数组所在地址:%p -- 数组第二元素地址:%p -- 数组第三元素地址:%p",d,d+1,d+2);
    NSLog(@"数组第一个元素:%d -- 数组第二元素地址:%d -- 数组第三元素地址:%d",*d,*(d+1),*(d+2));
    NSLog(@"基本数据类型a:%p -- 基本数据类型b:%p -- aa:%p",&a,&b,&aa);
}

运行结果:

结果:
 2021-10-12 12:29:14.881097+0800 指针偏移[70684:2791244] 数组所在地址:0x1040bb2a0 -- 数组首元素地址:0x1040bb2a0 -- 数组第二元素地址:0x1040bb2a4
 2021-10-12 12:29:14.881122+0800 指针偏移[70684:2791244] 数组所在地址:0x1040bb2a0 -- 数组第二元素地址:0x1040bb2a4 -- 数组第三元素地址:0x1040bb2a8
 2021-10-12 12:29:14.900159+0800 指针偏移[70684:2791244] 数组第一个元素:1 -- 数组第二元素地址:2 -- 数组第三元素地址:3

分析:

  • 数组名不是指针
  • &c是获取数组的空间地址,&c[0]是获取数组的第一个数据的空间地址,他们两个是一个地址
  • 因为数据是int型,每个数据占用4个字节,所以数据的地址都相隔四个字节,而指针本身是紧挨着的
  • d获取的是数组的指针,d+1是&c[1]地址空间的指针,指针的+1就会走到下个指针,我们可以通过指针的偏移来获取数据,下一个指针就是下一个数据的地址空间。
  • 数组的数据从前到后顺序存储,而不是从后到前

图示:

数组的指针偏移.png

你可能感兴趣的:(指针偏移的认识)