实用经验 28 充满疑惑的数组指针和指针数组

指针是C语言的精髓所在,同样也是C++语言的重要组成部分。如何高效的运用指针也从一个层面反映了C/C++语言的掌握水平,数组指针和指针数组是指针的高级应用,他们是指针和数组的组合应用。有些C++程序员从事软件开发好多年还无法区分指针数组和数组指针。

数组指针,可译为指向数组的指针。即是指向数组首元素地址的指针。一维数组指针定义形式为:

类型 (*数组标示符)[数组长度];,其中数组长度为所指向的数组长度,而非数组标示符的长度。例如:

int (*p)[10];  // p即为指向数组的指针,又称数组指针。

指针数组,可译为存放指针的数组,数组的每个元素均为指针。一维指针数组定义形式为:

类型 *数组标示符[数组长度];,数组长度存放指针的个数。例如:

int* p[10];    // 指针数组,表示数组p中的元素都为int型指针。

现在分析上述两种定义的差别。通过“int *p[10];”定义语句可定义一个指针数组。因为优先级的关系,所以p先与[]结合,说明p是一个数组,然后再与*结合说明数组p的元素是指向整型数据的指针。元素分别为p[0], p[1], p[2], …,p[7],相当于定义了10个整型指针变量,用于存放地址单元,在此,p就是数组元素为指针的数组,本质为数组。如果使用定义方式“int (*p)[8];”, p先与*号结合,形成一个指针,该指针指向的是有10个整型元素数组,p即为指向数组首元素地址的指针,其本质为指针。

现在我们讨论数组指针的用法。数组指针的用法可参考下面这个例子。

void main()
{
	int aiVal[2][2] = {{1,2},{3,4}};	//  定义一个2*2的二维数组
	int *piVal[2] = NULL;        		//  定义一个数组指针
	piVal = a;                 		    //  命piVal指向aiVal数组
}

将上述代码在VS2010编译器Debug模式下运行。aiVal内存布局如图4-4所示。aiVal和piVal调试信息如图4-5所示。
在这里插入图片描述

图4-4 aiVal、piVal内存布局图

在这里插入图片描述
图4-5 aiVal、piVal调试信息

从调试图我们可以看出,piVal的类型为int[2] 。piVal++实际上piVal的地址是增加2sizeof(int)个字节。二维数组aiVal其实有两个一维数组aiVal[0]和aiVal[1]组成。piVal+1指向aiVal[1]数组,piVal指向aiVal[0]数组。

也许你已经看出数组指针声明的元素数是和执行的数组元素个数是相同的。当然这是不是必须相同呢。那我们在看下面这个例子。

char (*pszVal)[2] = NULL;
char szVal[3] = {1, 2, 0};
pszVal = szVal;        // error C2440: “=”: 无法从“char [3]”转换为“char (*)[2]” 

在C++中,int (p)[5]表示一个指向二维数组的指针变量,该二维数组的列数必须为5。而指针数组intp[5]表示一个指针数组,它有5个下表变量p[0],p[1],p[2],p[3],p[4]均为指针变量。通常可用一个指针数组来指向一个二维数组。指针数组中的每个元素被赋予二维数组每一行的首地址,因此也可理解为指向一个一维数组。例如,下面的程序用一个指针数组指向二维数组每一行的首地址。

#include <stdio.h>    //头文件  
#include <stdlib.h> 
 
int main()  
{  
    int a[3][3]={{123}{456}{789}};//声明并初始化  
    int *p[3]={a[0],a[1],a[2]};  
    int i;  
 
    for(i=0;i<3;i++)        //循环输出  
    {  
        printf("%d %d %d\n"*p[i]*(p[i]+1)*(p[i]+2));  
    }  
 
    system("pause");  
    return 0;  
}

在上面的程序中,首先定义一个指针数组,并为数组的每个元素赋初始值,使其指向二维数组每一行的首地址。a[0]、a[1]、a[2]分别表示二维数组a每一行的首地址。数组元素p[0]的值为二维数组a中第一行的首地址,因为数组p[0]是一个指针,所以p[0]加上或减去一个整数n时,指针将指向后n个或前n个相同类型的元素。p[0]+0的值将是二维数组a第一行第一列的地址,p[0]+1的值是二维数组a第一行第二列的地址,p[0]+2的值是二维数组a第一行第三列的地址,如图4-6所示。得到指针所指向元素的地址后,使用运算符*即可得到该地址的值。所以,程序将输出二维数组a中每一行的三个元素。
在这里插入图片描述

图4-6 指针数组

小心陷阱

  • 在数组指针中,声明的维数表示指针数组的元素数。而不是指针本身的元素数。
  • 指针数组的每个元素均为指针。指向的数据类型为声明时的类型。声明时的元素数即是指针数组的元素数。
  • 数组指针可用于二维数组元素的操作,只要数组指针声明的元素数和二维数组第二维元素数一样,二维数组名可直接赋值予数组指针。

请谨记

  • 明确辨别指针数组和数组指针。不要将其混为一谈,指针数组表示声明的变量是一个数组,数组中的元素为指针。而数组指针则表示声明的变量为一个指针,此指针指向一个数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值