C生万物 | 指针初阶 · 入门篇-3

简介: C生万物 | 指针初阶 · 入门篇

五、指针和数组

关于指针聊了这么久,接下去我们看看指针和数组之间有什么联系,如果想了解数组相关知识的,可以看看这篇文章——> 窥探数组设计的种种陷阱

我们看一个栗子🌰

  • 在数组章节就有讲起过,数组名就是首元素地址,验证一下将它们的地址都打印出来可以发现是相同的


int main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
  printf("%p\n", arr);
  printf("%p\n", &arr[0]);
  return 0;
}

image.png


  • 因此我们就可以将数组名作为数组的首元素地址给到一个指针,通过这个指针就可以去遍历这个数组,因为arr[i]*(p + i)都可以访问到数组中下标为i这个元素,因此&arr[i]p + i所访问的地址也是一样的


int main()
{
  int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  int* p = arr;   //指针存放数组首元素的地址
  int sz = sizeof(arr) / sizeof(arr[0]);
  for (int i = 0; i < sz; i++)
  {
    printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p + i);
  }
  return 0;
}

image.png

  • 既然&arr[i]p + i所访问的地址也是一样的,那我们就可以通过*(p + i)去访问这个数组中的所有元素

image.png✒【总结一下】

  • 数组和指针不是一个东西,数组能够存放一组数,是一个连续的空间,它的大小取决于数组元素的类型和个数;而指针则是用来存放地址,它的大小取决于你当前编译器所运行的环境,是32位 / 64位
  • 数组和指针的联系在于:数组名是首元素地址,把数组名给到一个指针变量之后,可以通过这个指针变量来访问这个数组中的所有元素

六、二级指针

好,看完了上面的这些内部,你对指针的一些基础算是入门了,接下去我们来做一些提升,学习一下二级指针🗡

1、变量、指针、二级指针

  • 通过上面的学习可以知道,对于一个指针变量来说,可以接受一个变量的地址,那么这个指针其实就叫做【一级指针】,那我们知道对于一级指针来说也是有地址的,我也带你看过了,那现在我想做的一件事就是把一个一级指针的地址存放到一个变量里
  • 下面这个pp就是一个二级指针,它存放有一级指针p的地址


int a = 10;
int* p = &a;
int** pp = &p;
  • 现在我通过下面这张图为你做一个讲解。首先变量a的值为10,地址为0x00befd90,然后一级指着变量p存放了变量a的地址,所以可以说它指向a。对于变量p来说,它也有自己的地址,为0x00befd84,二级指针变量pp里则是存放了这个地址,所以可以说它指向p

image.png

  • 然后来解释一下有关指针变量前面的一些星号:对于变量p,它前面的*表示它是一个指针变量,【int】则表示它保存的一个int类型变量的地址,就说它指向一个整型变量
  • 对于变量pp,它前面的*表示它是一个指针变量,【int *】则表示它保存的一个int*类型变量的地址,就说它指向一个指针变量

👉万不可以把二级指针理解为就是前面两个星号这么简单,要将指针和地址之间的关系联系起来image.png

肯定还有同学没有理解,我通过一个生活小案例来说明一下

  • 其实【指针与地址】的关系就和【钥匙🔑与保险箱】的关系是一个道理,就比如说这个二级指针pp,它就是一把钥匙,它里面存放了一级指针p的地址,所以可以顺利地找p这个箱子,这样的话就可以通过这把钥匙打开这个箱子
  • 但是这个箱子里面呢存有一把小钥匙,也就是一级指针p,它里面呢存放有变量a的地址,通过这把钥匙你就可以找到变量a,然后便可以通过新找到的这把钥匙打开变量a这个箱子,里面就有一个数值为10,它就是你要找的那个宝藏【看过极限挑战的读者应该都明白】image.png

2、有关二级指针的运算

对二级指针有了一个初步的了解之后,我们来看看有关二级指针的一些运算

📚通过对二级指针进行一次解引用,可以获取到一级指针变量,重新改变指向

📚通过对二级指针进行两次解引用,可以获取到一级指针所存放的变量,重新改变值

  • 看到下面这段代码,我新定义了一个变量b,然后可以看到通过*pp对二级指针进行了一个解引用的操作,这就获取到了一级指针变量p,此时我将变量b的地址存放到它里面去,这也就改变了指针p的指向


int a = 10;
int b = 20;
int* p = &a;
int** pp = &p;
*pp = &b;
  • 我们可以通过DeBug调试来看看【上面是变化前,下面是变化后】

image.png

  • 可以观测到,一级指针变量p存放的地址以及值都发生了改变,而且二级指针pp里所存放的一级指针变量p也发生了变化。这就是一次解引用可以实现的操作

接下去我们来看看通过两次解引用可以做到什么

  • 看到如下代码,我通过两次解引用获取到了变量a的值,然后对其做了一个修改


int a = 10;
int* p = &a;
int** pp = &p;
printf("a = %d\n", a);
**pp = 200;
printf("a = %d\n", a);
  • 通过运行结果就可以看出a的值确实发生了变化,执行前和执行后的值有所不同

image.png

  • 通过DeBug调试也是可以看出因为pp里面存放有p的地址,而p里面又存放有a的地址,我们可以将这个二次解引用做一个分解。第一次解引用首先找到一级指针p,然后再进行一个解引用便找到了变量a,此时就有了一个【修改的权限】

image.png通过以上的叙述,相信你对二级指针有了一个初步的认识和理解,在之后的【指针进阶 · 提升篇】  中我还会再详解二级指针


这里补充一点,上面说到只要是指针均为4个字节,那对于二级指针来说呢?也是4个字节吗?

  • 可以看到,的确如此,无论是一级指针还是二级指针,其大小并不取决于指针本身的类型,而是取决于当前这段代码所处的平台,在32为平台下均为4个字节,在64位平台下均为8个字节

image.pngimage.png

相关文章
|
1月前
|
存储 编译器 C语言
C++入门2——类与对象1(类的定义和this指针)
C++入门2——类与对象1(类的定义和this指针)
30 2
|
6月前
|
存储 编译器 C语言
C语言初阶⑦(指针初阶)知识点+笔试题(上)
C语言初阶⑦(指针初阶)知识点+笔试题
42 0
|
3月前
|
存储 安全 编译器
C++入门 | auto关键字、范围for、指针空值nullptr
C++入门 | auto关键字、范围for、指针空值nullptr
65 4
|
3月前
|
Go 计算机视觉
Go从入门到放弃之指针
Go从入门到放弃之指针
|
4月前
|
存储 安全 编译器
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
|
4月前
|
编译器 C语言
【C语言初阶】指针篇—下
【C语言初阶】指针篇—下
|
4月前
|
存储 C语言
【C语言初阶】指针篇—上
【C语言初阶】指针篇—上
|
6月前
|
算法 测试技术 容器
【刷题】双指针入门
经过这四道题目的洗礼,我大概对双指针有了初步印象,接下来我会继续努力!!!
76 13
【刷题】双指针入门
|
6月前
入门后指针进阶习题深度分析
入门后指针进阶习题深度分析
40 1
下一篇
无影云桌面