C++中指针数组与数组指针

指针是C/C++语言的特色,而数组名与指针也有很多相似的地方,但这里所说的指针数组与数组指针是截然不同的两个概念。

指针数组:array of pointers,首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。

数组指针:a pointer to an array,首先它是一个指针,它指向一个数组。在32 位系统下永远是占4 个字节,至于它指向的数组占多少字节,指针本身并不知道。它是“指向数组的指针”的简称。

1. 指针数组

    定义:

elemtype *p[n]

    由于“[ ]”的优先级高于“*”,p先与“[ ]”结合,构成数组的定义,数组名为p。elemtype *修饰的是数组的内容,即数组的每个元素,这是一个elemtype型指针数组,它有n个指针类型的数组元素。
    指针数组如下处理就会很清楚:

typedef elemtype* etPtr;
etPtr p[n]; 

    一目了然,所以为了避免迷惑,做适当的typedef也是很有必要的。

    这里执行类似

p++;
P = &d;

    这样的赋值操作是错误的,因为此处的p是个右值,程序中只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放elemtype型变量的地址。

    但是

*p = &d;  //相当于p[0] = &d;

    这样的操作是正确的,这里*p表示指针数组的第一个元素的值,可以用来存放d的地址。

    如果要把一个二维数组赋给一个一维指针数组,则需要如下操作:

elemtype *p[n];
elemtype a[n][m];
for(i=0; i<n; i++)
    p[i]=a[i];

    这里elemtype *p[n] 表示一个一维数组内存放着n个指针变量,分别是p[0]、p[1]、p[2]...p[n],默认情况下这n个指针变量都是指向NULL的,所以要分别赋值。

2.数组指针(也称为行指针)

    行指针是一种形象的说法,比如现在有一个x行x列的表格。p指针指向第一行,如果p+1,那么此时p就指向下一行的首地址。普通指针+1 就指向下一个的地址。

    定义:

elemtype (*p)[n];  //此处()一定不能少

    由于“()”的优先级高,首先说明p是一个指针,指向一个elemtype型的一维数组。这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

    **或许这样写能更有助于理解,elemtype (*)[n] p,elemtype (*)[n]看作是一个指针类型,而p是指针变量。仅限私下自己理解,编译器可不这么想。

    通过定义数组指针的方式,使得一个指针变量与二维数组名具有相同的性质。

    如要将二维数组赋给一数组指针,应这样赋值:

elemtype a[n][m];
elemtype (*p)[m]; //该语句是定义一个数组指针,指向含m个元素的一维数组。
p = a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]

    此时执行p++后,p跨过行a[0][ ]指向了行a[1][ ]。

    这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C/C++语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。

    如果要表示数组中第i行第j列一个元素,以下四种表示方式是一样的:

*(p[i]+j)	//指针数组
*(*(p+i)+j)  //数组指针
(*(p+i))[j]  //数组指针
p[i][j]	//数组指针

----------我---是---分---割---线-------------------------------------------------------

为了方便理解和记忆,这里给出数组元素的指针表示法:

对于一维数组:
int a[10];
int *p;
int i
p = &a[0];  //等价于p = a;
a[i] 等价于 *(a+i) 等价于 *(p+i) 等价于 p[i]
&a[i] 等价于 a+i 等价于 p+i 等价于 &p[i]

对于二维数组:

int b[10][20]
可理解为:
typedef int A[20]
A b[10]
b  //为10个A类型的元素构成的一维数组变量,其元素为b[0],b[1]...b[9]
b[i]  //为20个int类型的元素构成的一维数组变量,其元素为b[i][0],b[i][1]...b[i][19]
b[i][j]  //为int类型的变量
b,&b[0]  //为变量b[0]的地址,类型为A*
b+i,&b[i]  //为变量b[i]的地址,类型为A*
b[0],&b[0][0]  //为变量b[0][0]的地址,类型为int*
b[0]+i*10+j,&b[i][j]  //为变量b[i][j]的地址,类型为int*

int *q = &b[0][0] 等价于 int *q = b[0]
b[i][j] 等价于 *(&b[0][0]+i*10+j) 等价于 *(b[0]+i*10+j) 等价于 *(q+i*10+j) 等价于 q[i*10+j]
A *t;  //等价于int (*t)[20];
t = &b[0];  //等价于t = b;
b[i][j] 等价于 *(*(&b[0]+i)+j) 等价于 *(*(b+i)+j) 等价于 *(*(t+i)+j) 等价于 t[i][j] 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值