深度解析指针与数组:探索内存管理的艺术

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 深度解析指针与数组:探索内存管理的艺术



1.数组名的理解

我们发现数组名和数组首元素的地址打印出的结果一模一样,数组名就是数组首元素(第一个元素)的地址。

数组名如果是数组首元素的地址,那下面的代码怎么理解呢?

输出的结果是:40,如果arr是数组首元素的地址,那输出应该的应该是4/8才对。

其实数组名就是数组首元素(第一个元素)的地址是对的,但是有两个例外:

sizeof(数组名),sizef中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节

&数组名,这里的数组名表示整个数组,取出的是整个数组的地址 (整个数组的地址和数组首元素的地址是有区别的)

除此之外,任何地方使用数组名,数组名都表示首元素的地址。

图解:

2.使用指针访问数组

为什么访问数组的时候可以使用指针呢?

1.数组在内存中是连续存放的

2.指针+-整数运算,方便我们获得每一个元素的地址

int main()
{
  int arr[10] = { 0 };
  //使用指针来访问数组
  int sz = sizeof(arr) / sizeof(arr[0]);
  //输入10个值
  int* p = arr;
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    //输入1个值
    scanf("%d", p+i);//p+i == &arr[i]
  }
  //输出10个值
  for (i = 0; i < sz; i++)
  {
    printf("%d ", i[arr]);//p[i]  arr[i]  *(arr+i)
  }
  return 0;
}

arr[i]==>*(arr+i)等价

1.数组就是数组,是一块连续的空间(数组的大小和数组元素个数和元素类型都有关系)
2.指针(变量)就是指针(变量),是!一个变量(4/8个字节)

数组与指针的联系:

3.数组名是地址,是首元素的地址
4.可是使用指针来访问数组

3.一维数组传参的本质

打印的值为1,是指针变量的大小,不是数组的大小

数组传参的时候,形参是可以写成数组的形式的
但是本质上还是指针变量
void Print(int arr[10])//int* arr
{
  int sz = sizeof(arr) / sizeof(arr[0]);//得不到元素个数的,算出来的是指针变量的大小
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
}
void Print(int* p,int sz) //应该是指针
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", *(p + i));
  }
}
int main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  Print(arr, sz);//arr 数组名就是数组首元素的地址
  //sizeof(arr)
  //&arr
  return 0;
}

1. 数组传参的本质是传递了数组首元素的地址,所以形参访问的数组和实参的数组是同一个数组的。

2.形参的数组是不会单独再创建数组空间的,所以形参的数组是可以省略掉数组大小的。

总结:一维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。

4 .冒泡排序

冒泡排序的核心思想:就是两两相邻的元素进行比较。

图示:

代码如下

升序
void bubble_sort(int arr[], int sz)
{
  int i = 0;
  //趟数
  for (i = 0; i < sz - 1; i++)
  {
    //假设已经有序了
    int flag = 1;
    //一趟排序的过程
    int j = 0;
    for (j = 0; j < sz-1-i; j++)
    {
      if (arr[j] > arr[j + 1])
      {
        int tmp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = tmp;
        flag = 0;
      }
    }
    if (flag == 1)
    {
      break;
    }
  }
}
void print_arr(int arr[], int sz)
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
}
int main()
{
  int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
  //排序
  int sz = sizeof(arr) / sizeof(arr[0]);
  bubble_sort(arr, sz);
  //打印
  print_arr(arr, sz);
  return 0;
}

避免已经排序结束了,但是还在循环

5.二级指针

int main()
{
  int a = 10;
  int* p = &a;//p就是一级指针
  int * * pp = &p;
  int** * ppp = &pp;
  int**** pppp = &ppp;
  //.....
  return 0;
}

解引用

6.指针数组

指针数组是数组还是指针?

是数组!

eg:好孩子,主语是孩子

我们类比一下,整型数组,是存放整型的数组,字符数组是存放字符的数组。
那指针数组呢?是存放指针的数组。

7.指针数组模拟二维数组

并不是真的二维数组,只是模拟出来的

图解:

parr[]是访问parr数组的元素,parr[i]找到的数组元素指向了整型一维数组,parr[i][j]就是整型一维数组中的素。

上述的代码模拟出二维数组的效果,实际上并非完全是二维数组,因为每一行并非是连续的。

希望对你有帮助!加油各位!!

每一次努力都是不凡的历练,每一点进步都是值得庆祝的胜利。你正在创造属于自己的辉煌,相信自己,一切皆有可能。

目录
相关文章
|
13天前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
29 3
|
14天前
|
存储 Java 编译器
Java内存模型(JMM)深度解析####
本文深入探讨了Java内存模型(JMM)的工作原理,旨在帮助开发者理解多线程环境下并发编程的挑战与解决方案。通过剖析JVM如何管理线程间的数据可见性、原子性和有序性问题,本文将揭示synchronized关键字背后的机制,并介绍volatile关键字和final关键字在保证变量同步与不可变性方面的作用。同时,文章还将讨论现代Java并发工具类如java.util.concurrent包中的核心组件,以及它们如何简化高效并发程序的设计。无论你是初学者还是有经验的开发者,本文都将为你提供宝贵的见解,助你在Java并发编程领域更进一步。 ####
|
8天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
27 4
|
12天前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
25 2
|
21天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
26 1
|
23天前
|
存储 Rust C#
内存指针解引用
【10月更文挑战第14天】
30 1
|
23天前
|
Rust 安全 Java
内存数组越界
【10月更文挑战第14天】
22 1
|
30天前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。
|
30天前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
30天前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。

推荐镜像

更多