C初阶--指针初阶(下):指针运算+指针和数组+二级指针+指针数组(下)

简介: C初阶--指针初阶(下):指针运算+指针和数组+二级指针+指针数组(下)

二.指针和数组


二者区别:

指针就是指针,不是数组

数组就是数组,也不是指针


如何求大小:

指针的大小:4/8个字节,指针是存放地址的,地址的存放需要多大空间,指针变量的大小就是多少

数组的大小:取决数组的元素个数和每个元素的类型

我们看一个例子:

#include <stdio.h>
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;
}

90556d13decb4efb815132353f8ec0a5.png

可见数组名和数组首元素的地址是一样的。

结论:数组名表示的是数组首元素的地址。(2种情况除外:sizeof(数组名)+&数组名)

那么这样写代码是可行的:

int arr [ 10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 };

int * p = arr ; //p 存放的是数组首元素的地址

既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问一个就成为可能。


☑️☑️☑️重点:

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

运行结果:

c6a84fbdfa4d4e0d89e21f7ac1ace0ad.png

 💾画图笔记:

a23f1e0e04bb4ebfb1d693809955681d.png

循环部分的代码也可以写成:

for (i = 0; i < sz; i++)
    {
        printf("%d ", i[arr]);
        //i[arr] -- *(i+arr)
        //arr[i] -- *(arr+i)
    }


💥注意的点:

三者等价:*(arr+i)-->*(p+i)-->arr[i]

不管是写成i[arr]还是arr[i],编译器都会转换成*(arr+i)或者*(i+arr)

所以 p+i 其实计算的是数组 arr 下标为i的地址。

那我们就可以直接通过指针来访问数组。

如下:


1.指针和数组间的联系:

#include<stdio.h>
int main()
{
  int arr[10] = { 0 };
  int* p = arr;
  int i = 0;
  //存放
  for (i = 0; i < 10; i++)
  {
    *p = i + 1;
    p++;
  }
  //打印
  p = arr;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", *(p + i));
  }
  return 0;
}


存放的另一种写法:

for(i=0;i<10;i++)

{

    *(p+i)=i+1;

}


图解:

8ff4c1fc015e45d69c6eb80bde397793.png

上述图解和代码证明了:

1.指针可以指向数组元素的

2.因为指针可以运算,所以借助于指针可以访问数组


2.用指针访问二维数组

int main()
{
  int arr[3][5];
  return 0;
}


等价的写法: 🚗

arr[i][j]  --> (*(arr+i))[j] -->*(*(arr+i)+j)


三.二级指针


指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?

答:二级指针

#include<stdio.h>
int main()
{
  int a = 10;//a是要在内存中申请4个字节的空间的
  //一级指针
  int* pa = &a;//0x0012ff40,pa是变量,用来存放地址,也得向内存申请,申请4/8
  //二级指针
  int** ppa = &pa;//0x0012ff48
  //三级指针
  int*** pppa = &ppa;
  printf("%d\n", **ppa);
  return 0;
}


✅✅注意:最右边的*间隔分开只是为了更好解释它是一个什么样的指针,空格加不加无所谓的

一级指针:

int* pa = &a;  -->     *表明pa是指针,而int表明pa指向的对象a的类型是int

二级指针:是用来存放一级指针变量的地址

int* * ppa = &pa  --> *告诉我们ppa是指针,而int*表明ppa指向的对象pa的类型是int*

如此类推....

可以打开内存监视窗口看一下情况,各个变量的地址和生成的对应指针存放的地址是一样的

568fd1e3f08140a0a27402fe4ca9b42a.png

画图:

64f18cd66bb244d882e90d76cc19a3f0.png

🅿️对于二级指针的运算有:

  • *ppa 通过对ppa中的地址进行解引用,这样找到的是 pa ,*ppa 其实访问的就是 pa .

int b = 20;

*ppa = &b;//等价于pa = &b;


  • **ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a .

**ppa = 30;

//等价于*pa = 30;

//等价于a = 30;

还有一点:其实在开发的过程中三级指针很少用。


四.指针数组


指针数组是指针还是数组? 答案:是数组。是存放指针的数组。

数组我们已经知道整形数组,字符数组。

int arr1[5];

char arr2 [ 6 ];


🚩1.存放整型指针的数组

#include<stdio.h>
int main()
{
  int* p;
  int a = 10;
  int b = 20;
  int c = 30;
  //指针数组--存放指针的数组
  int* arr[] = { &a,&b,&c };//
  int i = 0;
  for (i = 0; i < 3; i++)
  {
    printf("%d ", *(arr[i]));
  }
  char* arr2[5];
  float* arr3[5];
  return 0;
}


执行:

d18b4391846a488493d83e3ed93b8145.png

▶️关于这里的知识点总结:

42e44b55a7ed4908ada84f3c183b7bb8.png

除此之外还有:

   char* arr2[5];//存放字符指针数组

   float* arr3[5];//存放浮点型指针的数组

...等等数组


2.二级指针数组的应用

int main()
{
    char* arr[5];//{char* char* char* char* char*}
    char** p = arr;//&arr[0] - char**
    return 0;
}

b4515fa0bd37471fadb7b3a2fb4b06af.png

arr表示首元素的地址也就是&arr[0],我本以为它的类型在监视中是char**,结果是char*[5] -- 上图可知。

反思得:

其实首元素的地址:&arr[0]类型确实是char**,监视的时候是表示的是一个数组,监视的是数组类型而不是数组首元素地址的类型

原因:

监视窗口有自己的规则,这个不必深究


⁉️通过整型指针存放三个一维数组

#include<stdio.h>
int main()
{     //
  int arr1[] = { 1,2,3,4,5 };//数组arr1内部的元素是连续的,但是arr1,arr2,arr3三者不一定连续
  int arr2[] = { 2,3,4,5,6 };
  int arr3[] = { 3,4,5,6,7 };
  int* ptr[] = { arr1,arr2,arr3};
  int i = 0;
  for (i = 0; i < 3; i++)
  {
    int j = 0;
    for (j = 0; j < 5; j++)
    {
      printf("%d ", ptr[i][j]);
    }
    printf("\n");
  }
  return 0;
}


注意:数组arr1的内部元素是连续的,但是arr1,arr2,arr3三者不一定连续

执行结果:

2dc42d5395e742ed9ab3f3e1973c2714.png

本章完。欢迎大佬补充

目录
打赏
0
0
0
0
37
分享
相关文章
|
3月前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
52 3
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
3月前
|
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
81 4
|
3月前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
62 2
|
3月前
|
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
50 1
|
4月前
|
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
4月前
|
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等