对于一维数组a[i](a[i]类型不为char),a表示数组的首地址,即a=&a[0]。

int a[10];
cout<<a<<endl;
cout<<&a[0]<<endl;//两者相同,都表示数组a的首地址。
cout<<*a<<endl;
cout<<a[0]<<endl;//两者相同,都表示数组a的首元素a[0]。

对于字符串数组,使用输出数组名称指令则会直接输出整个字符串数组。

char str[10]={'1','2','3','4'};
cout<<str<<endl;//输出整个字符串
cout<<&str[0]<<endl;//输出整个字符串
cout<<*str<<endl;//输出首元素
cout<<(char *)str<<endl;//输出整个字符串
cout<<(int *)str<<endl;//输出字符串首地址
cout<<(void *)str<<endl;//输出字符串首地址
cout<<&str[1]<<endl;//输出234

综上,cout遇到输出字符类型的地址时,不会输出地址,而是输出该地址上的字符。所以如果想输出字符串数组的地址,需要把指针改为其他类型,如void或int。

指针存在类型 ,如int *p,p是int类型的指针,不可以指向double类型的地址

int *p p=p+1 加上了一个int的字节,即加了四个字节。
char *p p=p+1 加上了一个char的字节,即加了一个字节。

int a[10]={1,2,3};
cout<<*a<<endl;//结果为1
cout<<*(a+1)<<endl;//结果为2

指针存在着运算,此处说明一维数组分配的是一段连续的内存,可以通过某种运算公式得到地址。如要求a[5],地址即为a+5。

对于二维数组,以a[10][20]为例,其实分配的内存也是连续的一段,故可以通过某个固定的运算公式来得到地址。
要求a[5][5],地址即为a+5*20+5。其中20为第二维的长度。
对多维数组也是如此。很容易发现,地址的计算与一维的数目无关,这也是为何将数组作为参数被函数调用时不需要写明第一维的长度,但需写明除第一维外所有维度长度的原因。

二维数组的数组名也是表示数组的地址,但与一维数组不同的是,它表示的数组中的每一个元素都是一个数组的地址。

int a[10][20];
a[0][0]=1;
cout<<(*a)<<endl;//输出a[0],即a[0][0]的地址
cout<<*(*a)<<endl;//输出a[0][0]
cout<<*a[0]<<endl;//输出a[0][0]

在数组a中,每一个元素a[i]都代表着一个数组的地址,对应着二维数组的一行。因此,a与一维数组的首地址不同,如果想用一个指针p指向a,不可以运用与一维数组相同的方式。

int a[10][20];
//int *p=a;  编译报错
int (*q)[20]=a;//编译成功
int (*t)[20]=&a[0];//编译成功
int *p=a[0];//编译成功,此时p与q指向的地址相同,都为a[0]

此处的(*q)[20]意在告诉编译器,a所指向的数组中的元素都是一个长度为20的数组。

int a[10][20];
int (*q)[20]=a;
cout<<q<<endl;//0x61faf0
cout<<q+1<<endl;//0x61fb40
cout<<a[0]<<endl;//0x61faf0
cout<<a[0]+1<<endl;//0x61faf4

指针q的移动均是跨行移动,因为a在其指向的数组上,a[1]与a[2]之间分配的内存刚好相差一个第二维的长度,因此q每加1,相当于增加了20*4个字节,在十六进制下为50。而a[0]每移动1,其地址增加4个字节。

指针数组+二重指针

定义:

如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。

指针数组的定义形式一般为:

dataType *arrayName[length];

注意区别指向二维数组的指针(在上文为a)的定义为

dataType (*arrayName)[length]

int a=1,b=2,c=3;
int *p[5]={&a,&b,&c};//相当于p[0]=&a
cout<<*(p[1]);//输出2

对于指针数组,同样是一个数组,如果想要再使用一个指针p指向该数组的首地址,那指针p即是指针数组指针,即是一个二重指针

对二重指针的定义为

dataType **(arrayName);

具体使用举例

int a=1,b=2,c=3;
int *p[5]={&a,&b,&c};//相当于p[0]=&a
int **q=p;
cout<<*(q)<<endl;
cout<<p[0]<<endl;//两者输出结果相同

需要注意的是:
二重指针代表着这个指针指向的数组的类型是一个指针数组,即是数组中的每一个元素都是一个指针。
而二维数组中,数组名a作为地址,对应的数组的每一个元素是二维数组每一行的首地址(可认为是地址数组)。
故不可直接用二重指针指向a所在的地址。

int a[10][20];
int (* q)[20]=a;//正确
int **p=a;//错误

指针数组中的每一个指针指向地址时是相互独立的。

上文中a指向的数组中a[1]、a[2]是对应的二维数组的每一行的地址。我们可以对每一行分别用一个指针指向这一行的首地址,将一个二维数组所用的指针放进一个数组中,就得到了一个指针数组。
如果先定义了二维数组,再用指针数组去指向每一行的首地址,那么指针数组中的指针指向的地址便是连续的。

int *p[3];
int a[3][2];
for(register int i=0;i<3;i++){p[i]=a[i];//p[i]=&a[i][0];
}
cout<<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;
//输出0x61fe00 0x61fe08 0x61fe10

但如果先定义了指针数组,再让每一个指针去指向一个一维数组从而构成一个二维数组,那么每一个指针的内存分配就不一定连续

int *q[5];
int a[2],b[2],c[2];
q[0]=a;
q[1]=b;
q[2]=c;
cout<<q[0]<<" "<<q[1]<<" "<<q[2]<<endl;
//输出0x61fde8 0x61fde0 0x61fdd8

举一些函数对二维数组调用的例子

void BubbleSort(char a[10][20]);//正确
void Bubble(char a[][20], int n);//正确
void Bubble(char a[10][], int m);//错误,关键在除第一维之外的维度
void Bubble(char * a[10], int m);//正确
void Bubble(char a[][], int n, int m);//错误,理由如上
void Bubble(char ** a, int n, int m);//正确
void Bubble(char * a[], int n, int m);//正确,第一维不需要

上文中第4、6、7种调用方法与第1、2种所用的内存分配方法不同,在调用时有着不同的调用方式。

void dfs(char **a){return;
}
void dfs1(char *a[]){return;
}
int main(){char *p[5];dfs(p);dfs1(p);
}

指针的内容较为繁杂,故写下这篇文章便于自身理解,也希望各位读者可以对其提出宝贵的意见。

【学习笔记】数组的地址分配及指针数组的使用相关推荐

  1. Java快速入门学习笔记8 | Java语言中的数组

    有人相爱,有人夜里开车看海,有人却连LeetCode第一题都解不出来!虽然之前系统地学习过java课程,但是到现在一年多没有碰过Java的代码,遇到LeetCode不知是喜是悲,思来想去,然后清空自己 ...

  2. 数据结构与算法学习笔记之 从0编号的数组

    数据结构与算法学习笔记之 从0编号的数组 前言 数组看似简单,但掌握精髓的却没有多少:他既是编程语言中的数据类型,又是最基础的数据结构: 一个小问题: 为什么数据要从0开始编号,而不是 从1开始呢? ...

  3. Python学习笔记第二十九天(N维数组(ndarray))

    Python学习笔记第二十九天 N维数组(ndarray) 构建阵列 索引阵列 ndarray的内部内存布局 阵列属性 内存布局 数据类型 其他属性 阵列接口 ctypes外部功能接口 Array方法 ...

  4. 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  5. 2020-09-25C++学习笔记引用2:二级指针形参与指针形参的使用方法和区别重难点,主看综合代码(1、指针形参2、引用形参3、二级指针形参4、指针引用形参)

    2020-09-25C++学习笔记引用2:二级指针形参与指针引用搭配做形参的使用方法区别重难点,注意事项主看综合代码(1.指针形参2.引用形参3.二级指针形参4.指针引用形参) 1.指针引用 #inc ...

  6. 指针详解(包含指针,指针数组,数组指针,指向数组指针的指针,函数指针,函数指针数组,指向函数指针数组的指针)

    大家都知道,指针有双面性,灵活度高,但是运用时一定要避免野指针和空指针的出现.否则会出现一些意想不到的错误.话不多说,看下面的代码: int main() {int arr[10] = { 0 };/ ...

  7. 【C语言】函数指针数组和指向函数指针数组的指针

    一.函数指针数组 1.1函数指针数组的声明 函数指针数组的声明如下,所谓函数指针数组就是在之前的函数指针的基础上增加了[],由于[]的优先级高于*,故 pf先与[]结合,说明它是一个数组,再与*结合说 ...

  8. C语言指针的那些事:第三篇(函数指针,指针函数,函数指针数组,指向函数指针数组的指针)

    文章目录 1. 函数指针 1)函数指针的例题 2. 指针函数 3. 函数指针数组 1)函数指针数组的用途 4. 指向函数指针数组的指针 5. 一些后话 1. 函数指针 函数指针就是指向函数的指针:本质 ...

  9. 图解C语言中数组指针、指针数组、函数指针、函数指针数组、指向函数指针数组的指针

    关于C语言中数组指针.函数指针.指针数组.函数指针数组.指向函数指针数组的指针一直比较绕,稍微整理一下. 到底是指针还是数组? 其实到底是指针还是数组还是看变量名与[]先结合还是*先结合.我们知道C语 ...

最新文章

  1. [深入理解Android卷一全文-第九章]深入理解Vold和Rild
  2. python dataframe groupby_【Python数据分析基础】入坑必备的数据预处理操作
  3. 丢失__EVENTTARGET _dopost Asp.net自带隐藏域和脚本的现象
  4. android查看存储占用,Android获取App内存使用情况的方法
  5. Writing and Mapping classes(Chapter 3 of NHibernate In Action)
  6. python3学习之元组
  7. 一、Jquery入门(超详)
  8. 简单的三步教你下载PyCharm汉化插件,让你学习Python事功半倍
  9. Microbiome:鸡肠道微生物宏基因集的构建(张和平、魏泓、秦楠点评)
  10. java 5分钟_java计算下一个整5分钟时间点
  11. 手机卫星定位系统_北斗三号最后一颗卫星发射成功完成组网!为何手机上还显示GPS?...
  12. 【洛谷4920】[WC2015] 未来程序(提答题)
  13. 有符号数和无符号数在计算机中怎么区分?
  14. “最忆是杭州”再次上演,与新华三“谈谈新”
  15. SQL Server 扩展秘钥管理(EKM)
  16. 深入理解Android音视频同步机制(二)ExoPlayer的avsync逻辑
  17. Android TextView设置.9图片为背景,文字被遮挡
  18. 《鱿鱼游戏》的深刻,在于足够肤浅
  19. 云原生架构下的微服务选型和演进
  20. addoption php,无忧建站-ajax+php无刷新二级联动下拉菜单(省市联动)源码

热门文章

  1. ajax获取jsp数据,如何使用ajax调用从servlet到jsp获取arraylist数据
  2. 2022-2028全球与中国国内和国际物流服务市场现状及未来发展趋势
  3. 可以删除电脑文件的c语言程序,win7电脑c盘都有哪些文件可以删除
  4. 天池竞赛——服务器故障预测
  5. 词云中去重复的词_为什么要避免标题关键词重复?
  6. 微信h5支付(php版) 2019
  7. 快来看,你的盒子也能用OpenCV NPU后端啦
  8. Charles 解决抓包显示乱码问题 - 已解决
  9. Android中ButterKnife(黄油刀)的详细使用
  10. 中点画线完整算法c语言,中点画线算法