【018】C++的指针数组和数组指针

news/2024/4/19 0:06:47

C++ 指针数组和数组指针

  • 引言
  • 一、指针数组
    • 1.1、数值的指针数组
    • 1.2、字符的指针数组
    • 1.3、二维字符数组
  • 二、指针的指针
  • 三、数组指针
    • 3.1、数组首元素地址和数组首地址
    • 3.2、数组指针的使用示例
    • 3.3、二维数组和数组指针的关系
  • 四、多维数组的物理存储
  • 总结

引言


💡 作者简介:专注于C/C++高性能程序设计和开发,理论与代码实践结合,让世界没有难学的技术。包括C/C++、Linux、MySQL、Redis、TCP/IP、协程、网络编程等。
👉
🎖️ CSDN实力新星,社区专家博主
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【017】C++ 指针变量详解,理解指针变量

一、指针数组

指针数组本质上是数组,只是数组的每个元素为指针。要牢记这句话。
例如:

char *arr_ch[10];
short *arr_sh[10];
int * arr_i[10];
sizeof(arr_ch);// 40 Byte
sizeof(arr_sh);// 40 Byte
sizeof(arr_i);// 40 Byte

1.1、数值的指针数组

#include <iostream>
using namespace std;
int main(int argc,char **argv)
{int num1=1;int num2=2;int num3=3;int num4=4;int num5=5;int *arr[5]={&num1,&num2,&num3,&num4,&num5};int n=sizeof(arr)/sizeof(arr[0]);int i=0;for(i=0;i<n;i++){cout<<*arr[i]<<" ";}cout<<endl;return 0;
}

输出:

1 2 3 4 5

1.2、字符的指针数组

#include <iostream>
using namespace std;
int main(int argc,char **argv)
{char *arr[4]={"hehehehe","xixixixixi","lalalalala","hahahahaha"};int n=sizeof(arr)/sizeof(arr[0]);int i=0;for(i=0;i<n;i++){cout<<arr[i]<<endl;;}return 0;
}

在这里插入图片描述

1.3、二维字符数组

二维字符数组存放的是每个字符串,指针数组存放的是每个字符串的首元素的地址。要注意这个区别。

例如:

char arr[4][128]={"hehehehe","xixixixixi","lalalalala","hahahahaha"}

二、指针的指针

int num=100;
int *p=&num;
int **q=&p;//指针的指针

在这里插入图片描述
从这可以推导出,n级指针可以保存n-1级指针变量的地址。

三、数组指针

数组指针本质上是指针变量;保存的是数组的首地址。
数组指针+1跳过的是整个数组。

int arr[5]={1,2,3,4,5};
int (*p)[5]=NULL;//这个就是数组指针
cout<<sizeof(p)<<endl;// 输出4。因为是指针,在32位平台永远是4字节
cout<<"p="<<p<<endl;//输出0,因为上面把它指向NULL。
cout<<"p+1="<<p+1<<endl;//输出0x14,转换为10进制就是20,也就是20个字节。即4*5p=&arr;//数组指针保存数组的首地址

3.1、数组首元素地址和数组首地址

假设有这样一个数组:

int arr[]={10,20,30,40,50};

(1)数组首元素地址是 &arr[0],而且arr也是代表的数组首元素地址。arr+1跳过的是一个元素。

cout<<"arr = "<<arr<<endl;
cout<<"&arr[0] = "<<&arr[0]<<endl;
cout<<"arr + 1 = "<<arr+1<<endl;

输出:

arr = 0x62fe7c
&arr[0] = 0x62fe7c
arr + 1 = 0x62fe80

可以看到arr和arr+1的地址相差4字节。

(2)数组的首地址是&arr;&arr+1跳过的是整个数组。

cout<<"&arr = "<<&arr<<endl;
cout<<"&arr + 1 = "<<&arr+1<<endl;

输出:

&arr = 0x62fe7c
&arr + 1 = 0x62fe90

(3)对数组首地址取* 得到的是数组首元素地址。
在这里插入图片描述
(4)数组指针一般在函数参数中使用。

3.2、数组指针的使用示例

int arr[5]={1,2,3,4,5};
int (*p)[5]=&arr;
cout<<*((int *)(p+1)-2)<<endl;//输出4,分析:首先是p+1指向了数组末尾,减2就是往后移动2个,刚好是4。

3.3、二维数组和数组指针的关系

(1)理解二维数组,二维数组的数组名表示的是第0行的行地址,对行地址取地址得到的是列地址。假设有如下的二维数组:

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

在这里插入图片描述

arr[1];//arr是首元素地址,所以arr[1]=(*arr+1),也就是第1行第0列的列地址。
&arr[1];//(arr+1),第一行的行地址。
*arr+1;//第0行第一列的列地址。
arr[1]+2;//*(arr+1)+2,第一行第2列的列地址。
**arr;//a[0][0]

(2)二维数组和一维数组指针的关系:一维数组指针和二维数组名是完全等价的。
在这里插入图片描述
小结:n维数组和n-1维的数组指针等价。

四、多维数组的物理存储

不管是几维数组在物理上都是一维存储;在逻辑上是多维的而已。
在这里插入图片描述

#include <iostream>
using namespace std;
int main()
{int arr[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};int row=sizeof(arr)/sizeof(arr[0]);int col=sizeof(arr[0])/sizeof(arr[0][0]);int *p=&arr[0][0];for(int i=0;i<row*col;i++){cout<<p[i]<<" ";}cout<<endl;return 0;
}

输出:

1 2 3 4 5 6 7 8 9 10 11 12

总结

指针数组和数组指针是C++中比较常见的两种概念,它们都与数组和指针有关。

  1. 指针数组:指针数组是一个数组,其中每个元素都是一个指针。可以使用下标来访问该数组的各个元素,并且每个元素都可以用来存储指向不同类型对象的地址。例如:
int* ptrArr[10]; // 定义一个含有10个元素的int型指针数组

上述代码定义了一个名为ptrArr的包含10个元素的整型指针数组。可以通过下标访问这些元素,例如:

ptrArr[0] = new int(1); // 将第一个元素赋值为1
cout << *ptrArr[0] << endl; // 输出1
delete ptrArr[0]; // 释放内存
  1. 数组指针:数组指针是一个指向数组的指针。它本身就是一个变量,但可以通过它来访问所引用的整个数组。例如:
int arr[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
int (*p)[4] = arr; // 定义名为p的二维整型数组指针并将其初始化为arr

上述代码定义了一个名为p的二维整型数组指针,并将其初始化为arr。可以通过p来访问整个数组,例如:

cout << p[0][2] << endl; // 输出3

需要注意的是,由于数组指针实际上是指向一个数组的指针,因此它的类型必须与所指向的数组类型相匹配。

在这里插入图片描述


https://dhexx.cn/news/show-4626953.html

相关文章

VTK 开发中遇到问题整理

1 Generic Warning VTK 开发 中是到 vtkOutputWindow 弹窗并提示Generic Warning&#xff1a;… vtkOutputWindow 弹窗 解决方法&#xff1a; 添加&#xff1a; #include <vtkOutputWindow.h> 在 main.cpp函数中添加&#xff1a; vtkOutputWindow::SetGlobalWarningD…

四、若依(前后端分离)项目构建docker 镜像

若依(前后端分离&#xff09;项目构建docker 镜像 1. 构建好ruoyi-admin.jar包&#xff0c;上传到服务器项目目录下 2. 创建conf目录将若依项目&#xff08;Spring boot &#xff09;配置文件修改好&#xff0c;上传存入conf目录 注意&#xff1a;这里的地址不能写127.0.0.1和…

Rust每日一练(Leetday0013) 解数独、外观数列、组合总和

目录 37. 解数独 Sudoku Solver &#x1f31f;&#x1f31f;&#x1f31f; 38. 外观数列 Count and Say &#x1f31f;&#x1f31f; 39. 组合总和 Combination Sum &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Gola…

2023年第三届陕西省大学生网络安全技能大赛--本科高校组 Reverse题解

文章目录 一. 我的upx -d怎么坏了1. 查看节区信息2. 动态调试脱壳3.输出迷宫图4.走迷宫 二. babypython1.字节码简单分析2. gpt分析3. 程序逻辑4.解题脚本 三. BadCoffee1. 相关文章2.解混淆3.解题脚本 四. Web&Assembly(暂时没复现出来,提供一些相关文章)总结 这次比赛做出…

【Linux系统编程】19.dup、dup2

目录 dup 参数oldfd 返回值 测试代码1 测试结果 dup2 参数oldfd 参数newfd 返回值 测试代码2 测试结果 测试代码3 测试结果 文件重定向。 dup 文件描述符拷贝。 使用现有的文件描述符&#xff0c;拷贝生成一个新的文件描述符&#xff0c;且函数调用前后这个两个文…

基于SpringBoot+Mybatis+Mysql+vue校园二手交易市场

基于SpringBootMybatisMysqlvue校园二手交易市场 一、系统介绍1、系统主要功能&#xff1a;2、环境配置 二、功能展示1.主页(客户)2.登陆、注册&#xff08;客户&#xff09;3.我的购物车(客户)4.我的商品详情(客户)5.我的商铺&#xff08;客户、商家&#xff09;6.我的信息&am…

从实习到秋招成为一名安全工程师,我是怎么做的

前言 借朋友口述总结了安全招聘面试经历分享&#xff0c;希望更多的人看到这篇文&#xff0c;从中得到启发&#xff0c;找到自己心仪的工作。 基本情况 签了字节的三方&#xff0c;秋招终于告一段落。从八月份边实习边准备秋招到现在&#xff0c;经历了许多&#xff0c;这篇帖…

ChatGPT常见的报错解决方法(全网最全解决方法)

因为最近在使用ChatGPT的过程中&#xff0c;时常会出现一些错误提示&#xff0c;为了方便自己快速解决问题&#xff0c;所以也搜集了一些其他博主的解决方法&#xff0c;以下是整理的内容。 目录 1、拒绝访问 2、Access denied错误 3、We have detected suspicious 错误 4…

智能型数字档案馆构建设想

档案作为企业正式权威的数据资源&#xff0c;具有其历史传承和凭证唯一性等特点&#xff0c;随着企业的数字化转型&#xff0c;档案工作更需要数字化转型&#xff0c;档案管理与利用急需借助信息技术手段来管理好和记录好&#xff0c;急需挖掘档案资源&#xff0c;发挥其价值&a…

网络安全工程师面试题(附答案解析)

前言 有不少小伙伴面临跳槽或者找工作&#xff0c;本文总结了常见的安全岗位面试题&#xff0c;方便各位复习。祝各位事业顺利&#xff0c;财运亨通。在网络安全的道路上越走越远&#xff01;。 注&#xff1a;所有的资料都整理成了PDF&#xff0c;面试题和答案将会持续更新&a…