【018】指针的指针: C++ 指针数组、数组指针深入解析

引言


💡 作者简介:专注分享高性能服务器后台开发技术知识,涵盖多个领域,包括C/C++、Linux、网络协议、设计模式、中间件、云原生、数据库、分布式架构等。目标是通过理论与代码实践的结合,让世界上看似难以掌握的技术变得易于理解与掌握。公众号《Lion 莱恩呀》。
👉
🎖️ CSDN实力新星、专家博主,阿里云博客专家、华为云云享专家
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【017】C++ 指针变量详解,理解指针变量
🔔 下一篇:【019】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*5

p=&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

可以看到arrarr+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]; // 释放内存
    
  2. 数组指针:数组指针是一个指向数组的指针。它本身就是一个变量,但可以通过它来访问所引用的整个数组。例如:

    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
    

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

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lion Long

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值