美文网首页面试专辑
指针偏移的认识

指针偏移的认识

作者: iOS之文一 | 来源:发表于2021-10-13 18:45 被阅读0次

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:<NSperson: 0x105014c50> -- 变量地址:0x1040bb2b8
 2021-10-12 12:29:14.881069+0800 指针偏移[70684:2791244] 引用类型的指针person2:<NSperson: 0x105013d90> -- 变量地址: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

相关文章

  • 指针偏移的认识

    OC底层原理探索文档汇总[https://www.jianshu.com/p/04883ea4f5aa] 以基本数...

  • C++指针偏移

    最近在重新学习一遍C++的内容,由于C++的指针部分比较复杂,而且很抽象所以大学的时候学过的东西现在也忘了好多。这...

  • Golang 指针

    指针 区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。Go语言当中的指针涉及到三个点:指...

  • 数组元素表示方法

    下标法: 数组名[下标] a[i] 首地址法: *(首地址+偏移量) *(a+i) 指针变量法: *指针变量 *...

  • Go语言基础之指针

    区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。 要搞明白Go语言中的指针需要先知道3个...

  • C 笔记

    0722 结构体指针加1后,指针的偏移量为sizeof(struct); 示例代码如下: 运行结果如下: 0723...

  • JS的类与C++的类的区别

    C++的代码都会编译成底层的代码后才被执行。其中对象访问成员的语句,都会在编译阶段解析为对象指针+偏移。偏移的数值...

  • 分析objc_class中的cache

    在 指针偏移&读取bits信息& class_rw_t[https://www.jianshu.com/p/bc1...

  • iOS汇编基础(四)指针

    一 基本运算 1. 加法 运行结果为:104a为指向int类型的指针,a++相当于指针偏移寻找下一个int,int...

  • More effective C++

    不要对数组使用多态。 由于指向派生类和基类的指针,其各元素与数组首地址的偏移基本是不同的这就导致了当基类指针指向派...

网友评论

    本文标题:指针偏移的认识

    本文链接:https://www.haomeiwen.com/subject/ltjeoltx.html