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

【学习笔记】数组的地址分配及指针数组的使用,第1张

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

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

int a[10];
cout< 

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

char str[10]={'1','2','3','4'};
cout< 

综上,cout遇到输出字符类型的地址时,不会输出地址,而是输出该地址上的字符。所以如果想输出字符串数组的地址,需要把指针改为其他类型,如char或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< 

指针存在着运算,此处说明一维数组分配的是一段连续的内存,可以通过某种运算公式得到地址。如要求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)< 

在数组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的移动均是跨行移动,因为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)< 

需要注意的是:
二重指针代表着这个指针指向的数组的类型是一个指针数组,即是数组中的每一个元素都是一个指针。
而二维数组中,数组名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< 

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

int *q[5];
int a[2],b[2],c[2];
q[0]=a;
q[1]=b;
q[2]=c;
cout< 

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

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);
}

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4750316.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-08
下一篇 2022-11-08

发表评论

登录后才能评论

评论列表(0条)

保存