c++笔记--指针数组、数组指针、多维数组

写在前面

先把一个题目贴出来,以题来学习数组指针与数组指针、多维数组之间的关系

#include<stdio.h>

int main()
{
	char s[][10]={"KAIKEBA","XINZHIKE","LINUX","AIOT0622"}; 
	char *ss[]={s+1,s+3,s+2,s};  	
	char **sss=ss;                  
	
	printf("%s\n",*++sss);	
	printf("%c\n",--*++*sss++);	
	printf("%s\n",sss[-2]+1);	
	printf("%c\n",*sss[-1]+3);	
	printf("%s\n",++*(sss--));
		
	return 0;	
}
	

得到答案很简单,跑一遍代码就行‘了,但是我们来一步一步的分析

1、先来理解一些概念

一、指针数组与数组指针

(1)指针数组的实质是一个数组,这个数组中存储的内容全部是指针变量。
(2)数组指针的实质是一个指针,这个指针指向的是一个数组。

int *p;	
int p[10];
int *p[10];
int (*p)[10];    
分析方法:
第一步:找核心;
第二步:找结合;
第三步:继续向外结合直到整个符号完。

①int *p;
核心是p,p和 * 结合是指针。所以i nt*p;是定义了一个指针

②int p[10];
核心是p,p和 [10] 结合是数组。所以 int p[5];是定义了一个数组

③int *p[10];
核心是p,这时候p先和[10]结合还是先和 * 结合,查优先级表得到[]优先级更高。所以p先和[10]结合成为数组(在这里就决定了 *p[10]的本质是一个数组还是指针)。 p[10]这个数组再和 * 结合 ,所以得到结果,有一个数组有10个元素,其元素都是指针,即指针数组。
在这里插入图片描述
④ int (*p)[10];
核心是p,小括号优先级更高,所以p先和 * 结合成为指针,*p这个指针再和数组结合,所以有一个指针,该指针指向一个数组,即数组指针。
在这里插入图片描述

指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身的大小决定,每一个元素都是一个指针,在32位系统下任何类型的指针永远是占8个字节。它是“储存指针的数组”的简称。

数组指针:首先它是一个指针,它指向一个数组。在32 位系统下任何类型的指针永远是占8个字节,至于它指向的数组占多少字节,不知道,具体要看数组大小。它是“指向数组的指针”的简称。

二、在数组中* p +1 与 * (p+1) 的区别

#include <stdio.h> 

int main()
{
   char a[5]={'A','B','C','D'};
   char (*p3)[5] = &a;
   
   printf("%p\n",*p3);
   printf("%p\n",*(p3+1));
   printf("%p\n",*p3+1);
   printf("%p\n",a);   
  
   return 0;
}

得到的结果是
在这里插入图片描述

所以由上面这个图就可以知道 *(p +1) 是偏移了一个数组空间,而 *p+1只是地址先取 *p 的地址然后加一

三、数组名的三种含义

1、数组名可以代表整个数组
2、数组的首地址
3、数组首个元素的地址
在这里插入图片描述

2、先来分析这个题目

	char s[][10]={"KAIKEBA","XINZHIKE","LINUX","AIOT0622"}; 
	char *ss[]={s+1,s+3,s+2,s};   
	char **sss=ss;  

其中s很简单是一个二位数组,4行10列;ss是一个指针的数组 ,存放的是指向s[1][0] 的地址的指针 ,指向s[3][0]的地址的指针….每个指针相差8个字节,sss是二级指针存放的是指针数组名,也可以说是指向指针数组ss的首元素sss与ss是完全相同的。

我们先假设 s 的地址为 0x100,所以s[1][0]的地址为0x10a,s[2][0]的地址为0x114,s[3][0]的地址为0x11e,
对应的存储内容为"KAIKEBA",“XINZHIKE”,“LINUX”,“AIOT0622”

假设ss的地址为0x200,ss[1]的地址为0x208,ss[2]的地址为0x210,ss[3]的地址为0x218
对应的存储内容为 0x10a 0x11e 0x114 0x100
在这里插入图片描述

3、题目答案:

①++*sss = *(0x200 + 8) = *(0x208)= “AIOT0622”
sss的地址为0x208
先是对sss解指针操作,得到的是ss[0]指针,也就是 s+1指针也就是s[1][0]
②- - ++*sss++ = - - ++ (0x208) = - -++(0x11e) = - -*0x11f= - - ‘I’(asll码)= ’H’
sss的地址为 0x210 ss[1] =“HIOT0622”
③ sss[-2]+1 = *(sss–2)+1 = *(0x210 - 10)+1 = *(0x200) +1 = “XINZHIKE”+1 = “INZHIKE’’
未对sss/ss做出改变
④*sss[-1]+3 = *(*(sss-1))+3 = *(*(3d0-8))+3 = *(3fe)+3= ‘H’+3=‘K‘
未对sss/ss做出改变
⑤++*(sss–) = ++*(0x210) = ++( 0x114 ) = ” HINUX” + 1 = “INUX”
sss的地址为 0x208

最后ss为{“XINZHIKE” “HOT0622” “INUX” “KAIKEBA” }

由于在①②⑤中有++或者–所以其操作是对sss本身进行的操作,其操作过后s二维数组发生了新的变化,而在③④无++或者–,对s[4][5]其自身没有变化,这就和值传递与地址传递的区别、形参使用普通类型和指针类型区别类似;a- 3和a+3中a的值是否改变一样

程序跑完的结果:
在这里插入图片描述

分析的结果与程序跑出来的结是相同的,在这个题目中弯弯绕绕比较多,必须一步步的分析才能得到答案

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值