8.3 指针数组与指向指针的指针变量
8.3.1 指针数组
如果数组元素都是相同类型的指针,则称这个数组为指针数组。所谓相同类型的指针是说指针所指向的对象类型是相同的。
例如,语句int *p[5];定义了一个指针数组。在指针数组的定义中有两个运算符:*和[],运算符[]的优先级高于*,所以*p[5]等价于*(p[5]),p[5]表示一个数组,而*表示后面的对象为指针变量,合在一起*p[5]表示一个指针数组。该数组包含5个元素,每个元素都是指向int型的指针。
指针数组一般用于处理二维数组。使用指针处理多个字符串比用二维字符数组处理字符串更加方便。
例如:
char *pcolor[5]={"Red","Yellow","Green","Blue","Orange"};
char scolor[5][7]={"Red","Yellow","Green","Blue","orange"};
声明语句char *pcolor[5]={"Red","Yellow","Green","Blue","Orange"};表示将字符串"Red"、"Yellow"、"Green"、"Blue"、"Orange"的首地址分别存放到pcolor[0]、pcolor[1]、pcolor[2]、pcolor[3]、pcolor[4]中。
声明语句char scolor[5][7]={"Red","Yellow","Green","Blue","orange"};表示将字符串"Red"、"Yellow"、"Green"、"Blue"、"Orange"的各个字符分别存放到scolor数组对应的单元中。例如将'Y'存放到scolor[1][0]中。
对于二维数组,每个字符串所占内存的大小是一致的,所以取最长字符串的长度作为二维数组列的大小。从图8-3中可以看出,有些内存单元是空的。特别是当所处理的多个字符串长度相差比较大时,就更显得浪费内存空间。
用指针数组存储字符串可以节省存储空间,每个字符串所占的存储单元可以不等长。
例8-7 输入月份(1~12),输出该月份所在季节的英文名称。
#include
void main()
{char *pseason[4]={"Spring","Summer","Autumn","Winter"};
int month;
char ch;
while(1)
{cout<<"input month(1~12)=/n";
cin>>month;
switch(month)
{case 12:case 1:case 2:
cout< case 3:case 4:case 5:
cout< case 6:case 7:case 8:
cout< case 9:case 10:case 11:
cout< default:{cout<<"input data error.please try again!"< }
cout<<"continue(y/n)?"< cin>>ch;
if(ch=='y' || ch=='Y')
continue;
else
break;
}
}
例如,语句int *p[5];定义了一个指针数组。在指针数组的定义中有两个运算符:*和[],运算符[]的优先级高于*,所以*p[5]等价于*(p[5]),p[5]表示一个数组,而*表示后面的对象为指针变量,合在一起*p[5]表示一个指针数组。该数组包含5个元素,每个元素都是指向int型的指针。
指针数组一般用于处理二维数组。使用指针处理多个字符串比用二维字符数组处理字符串更加方便。
例如:
char *pcolor[5]={"Red","Yellow","Green","Blue","Orange"};
char scolor[5][7]={"Red","Yellow","Green","Blue","orange"};
声明语句char *pcolor[5]={"Red","Yellow","Green","Blue","Orange"};表示将字符串"Red"、"Yellow"、"Green"、"Blue"、"Orange"的首地址分别存放到pcolor[0]、pcolor[1]、pcolor[2]、pcolor[3]、pcolor[4]中。
声明语句char scolor[5][7]={"Red","Yellow","Green","Blue","orange"};表示将字符串"Red"、"Yellow"、"Green"、"Blue"、"Orange"的各个字符分别存放到scolor数组对应的单元中。例如将'Y'存放到scolor[1][0]中。
对于二维数组,每个字符串所占内存的大小是一致的,所以取最长字符串的长度作为二维数组列的大小。从图8-3中可以看出,有些内存单元是空的。特别是当所处理的多个字符串长度相差比较大时,就更显得浪费内存空间。
用指针数组存储字符串可以节省存储空间,每个字符串所占的存储单元可以不等长。
例8-7 输入月份(1~12),输出该月份所在季节的英文名称。
#include
void main()
{char *pseason[4]={"Spring","Summer","Autumn","Winter"};
int month;
char ch;
while(1)
{cout<<"input month(1~12)=/n";
cin>>month;
switch(month)
{case 12:case 1:case 2:
cout< case 3:case 4:case 5:
cout< case 6:case 7:case 8:
cout< case 9:case 10:case 11:
cout< default:{cout<<"input data error.please try again!"< }
cout<<"continue(y/n)?"< cin>>ch;
if(ch=='y' || ch=='Y')
continue;
else
break;
}
}
8.3.2 指向一维数组的指针变量
可以声明一个指针变量使其只能指向一维数组,声明的格式为:
<数据类型> <(*变量名)> <[元素个数]>
其中,<数据类型>表示一维数组元素的数据类型;*表示<变量>是指针;[ ]表示是数组, <[元素个数]>表示一维数组的大小。因为运算符[ ]的优先级高于*,所以用圆括号()将*与指针变量名括起来以改变运算符的优先级顺序,使*先作用于指针变量,然后再与[ ]结合,形成指向一维数组的指针变量。
指向一维数组的指针变量用于处理二维数组是非常方便的。
例如,在程序中有下列声明:
int b[3][5]={12,36,62,14,56,98,74,63,56,99,55,88,33,22,11};
int (*p)[5]=b;
那么,p表示指向数组b的行指针。如果将指针的初始化(*p)[5]=b;误写作(*p)[5]=b[0];会出现语法错误,因为指针p已被定义成指向一维数组的指针。
例8-8 阅读下列程序,写出运行结果。
#include <iostream.h>
void main()
{int b[3][5]={12,36,62,14,56,98,74,63,56,99,55,88,33,22,11};
int (*p)[5]=b;
int i,j;
cout<<"输出b数组每行的首地址:/n";
for(i=0;i<3;i++)
cout<<p+i<<" ";
cout<<endl;
for(i=0;i<40;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
cout<<p[i]<<" ";
cout<<endl;
cout<<"输出b数组每个元素的地址:/n";
for(i=0;i<3;i++)
{for(j=0;j<5;j++)
cout<<*(p+i)+j<<" ";
cout<<endl;
}
for(i=0;i<60;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
{for(j=0;j<5;j++)
cout<<p[i]+j<<" ";
cout<<endl;
}
cout<<"输出b数组每个元素的值:/n";
for(i=0;i<3;i++)
{for(j=0;j<5;j++)
cout<<*(*(p+i)+j)<<" ";
cout<<endl;
}
for(i=0;i<20;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
{for(j=0;j<5;j++)
cout<<p[i][j]<<" ";
cout<<endl;
}
}
程序运行的结果为:
输出b数组每行的首地址:
0x0065FDBC 0x0065FDD0 0x0065FDE4
-----------------------------------------------------------
0x0065FDBC 0x0065FDD0 0x0065FDE4
输出b数组每个元素的地址:
0x0065FDBC 0x0065FDC0 0x0065FDC4 0x0065FDC8 0x0065FDCC
0x0065FDD0 0x0065FDD4 0x0065FDD8 0x0065FDDC 0x0065FDE0
0x0065FDE4 0x0065FDE8 0x0065FDEC 0x0065FDF0 0x0065FDF4
----------------------------------------------------------------------------------------------------
0x0065FDBC 0x0065FDC0 0x0065FDC4 0x0065FDC8 0x0065FDCC
0x0065FDD0 0x0065FDD4 0x0065FDD8 0x0065FDDC 0x0065FDE0
0x0065FDE4 0x0065FDE8 0x0065FDEC 0x0065FDF0 0x0065FDF4
输出b数组每个元素的值:
12 36 62 14 56
98 74 63 56 99
55 88 33 22 11
--------------------------------
12 36 62 14 56
98 74 63 56 99
55 88 33 22 11
对于指向一维数组的指针可以使用其下标形式、也可以使用指针形式访问数组元素。下列几种表示形式是等价的。
地址的等价形式:
p+i p[i] *(p+i) 都表示b数组第i+1行的第1个元素的首地址
*(p+i)+j p[i]+j &p[i][j] 都表示b数组第i+1行、第j+1列元素的地址
值的等价形式:
*(*(p+i)+j) *(p[i]+j) p[i][j] 都表示b数组第i+1、第j+1列元素的值
<数据类型> <(*变量名)> <[元素个数]>
其中,<数据类型>表示一维数组元素的数据类型;*表示<变量>是指针;[ ]表示是数组, <[元素个数]>表示一维数组的大小。因为运算符[ ]的优先级高于*,所以用圆括号()将*与指针变量名括起来以改变运算符的优先级顺序,使*先作用于指针变量,然后再与[ ]结合,形成指向一维数组的指针变量。
指向一维数组的指针变量用于处理二维数组是非常方便的。
例如,在程序中有下列声明:
int b[3][5]={12,36,62,14,56,98,74,63,56,99,55,88,33,22,11};
int (*p)[5]=b;
那么,p表示指向数组b的行指针。如果将指针的初始化(*p)[5]=b;误写作(*p)[5]=b[0];会出现语法错误,因为指针p已被定义成指向一维数组的指针。
例8-8 阅读下列程序,写出运行结果。
#include <iostream.h>
void main()
{int b[3][5]={12,36,62,14,56,98,74,63,56,99,55,88,33,22,11};
int (*p)[5]=b;
int i,j;
cout<<"输出b数组每行的首地址:/n";
for(i=0;i<3;i++)
cout<<p+i<<" ";
cout<<endl;
for(i=0;i<40;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
cout<<p[i]<<" ";
cout<<endl;
cout<<"输出b数组每个元素的地址:/n";
for(i=0;i<3;i++)
{for(j=0;j<5;j++)
cout<<*(p+i)+j<<" ";
cout<<endl;
}
for(i=0;i<60;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
{for(j=0;j<5;j++)
cout<<p[i]+j<<" ";
cout<<endl;
}
cout<<"输出b数组每个元素的值:/n";
for(i=0;i<3;i++)
{for(j=0;j<5;j++)
cout<<*(*(p+i)+j)<<" ";
cout<<endl;
}
for(i=0;i<20;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
{for(j=0;j<5;j++)
cout<<p[i][j]<<" ";
cout<<endl;
}
}
程序运行的结果为:
输出b数组每行的首地址:
0x0065FDBC 0x0065FDD0 0x0065FDE4
-----------------------------------------------------------
0x0065FDBC 0x0065FDD0 0x0065FDE4
输出b数组每个元素的地址:
0x0065FDBC 0x0065FDC0 0x0065FDC4 0x0065FDC8 0x0065FDCC
0x0065FDD0 0x0065FDD4 0x0065FDD8 0x0065FDDC 0x0065FDE0
0x0065FDE4 0x0065FDE8 0x0065FDEC 0x0065FDF0 0x0065FDF4
----------------------------------------------------------------------------------------------------
0x0065FDBC 0x0065FDC0 0x0065FDC4 0x0065FDC8 0x0065FDCC
0x0065FDD0 0x0065FDD4 0x0065FDD8 0x0065FDDC 0x0065FDE0
0x0065FDE4 0x0065FDE8 0x0065FDEC 0x0065FDF0 0x0065FDF4
输出b数组每个元素的值:
12 36 62 14 56
98 74 63 56 99
55 88 33 22 11
--------------------------------
12 36 62 14 56
98 74 63 56 99
55 88 33 22 11
对于指向一维数组的指针可以使用其下标形式、也可以使用指针形式访问数组元素。下列几种表示形式是等价的。
地址的等价形式:
p+i p[i] *(p+i) 都表示b数组第i+1行的第1个元素的首地址
*(p+i)+j p[i]+j &p[i][j] 都表示b数组第i+1行、第j+1列元素的地址
值的等价形式:
*(*(p+i)+j) *(p[i]+j) p[i][j] 都表示b数组第i+1、第j+1列元素的值
8.3.3 指向指针的指针变量
如果指针变量中存放的是另一个指针的地址就称该指针变量为指向指针的指针变量。指向指针的指针变量也称为二级指针。其声明的语法格式为:
<数据类型> **<变量名>
两个符号**表示后面声明的变量为指向指针的指针变量。
例如,有如下声明语句:
int x=32;
int *p=&x;
int **pp=&p;
则x、p和pp三者之间的关系如图8-4所示。
指针变量p是一级指针,它指向x;指针变量pp是二级指针,它指向p。通过p和pp都可以访问x。*pp表示它所指向变量p的值,即x的地址;**pp表示它所指向的变量p所指向变量的值,即x的值。
指向指针的指针变量多用于访问二维数组。
例8-9 阅读下列程序,写出运行结果。
#include <iostream.h>
void main()
{int b[3][4]={12,36,62,56,98,63,56,99,88,32,66,22};
int *p[3]={b[0],b[1],b[2]};
int **pp=p;
int i,j;
cout<<"输出b数组每行的首地址:/n";
for(i=0;i<3;i++)
cout<<*pp++<<" ";
cout<<endl;
for(i=0;i<40;i++) cout<<"-";cout<<endl;
pp=p;
for(i=0;i<3;i++)
cout<<pp[i]<<" ";
cout<<endl;
for(i=0;i<40;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
cout<<p[i]<<" ";
cout<<endl;
cout<<"输出b数组每个元素的地址:/n";
for(i=0;i<3;i++)
{for(j=0;j<4;j++)
cout<<*(pp+i)+j<<" ";
cout<<endl;
}
for(i=0;i<50;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
{for(j=0;j<4;j++)
cout<<p[i]+j<<" ";
cout<<endl;
}
cout<<"输出b数组每个元素的值:/n";
for(i=0;i<3;i++)
{for(j=0;j<4;j++)
cout<<*(*(pp+i)+j)<<" ";
cout<<endl;
}
for(i=0;i<20;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
{for(j=0;j<4;j++)
cout<<p[i][j]<<" ";
cout<<endl;
}
}
程序运行的结果为:
输出b数组每行的首地址:
0x0065FDC8 0x0065FDD8 0x0065FDE8
-------------------------------------------------------------
0x0065FDC8 0x0065FDD8 0x0065FDE8
-------------------------------------------------------------
0x0065FDC8 0x0065FDD8 0x0065FDE8
输出b数组每个元素的地址:
0x0065FDC8 0x0065FDCC 0x0065FDD0 0x0065FDD4
0x0065FDD8 0x0065FDDC 0x0065FDE0 0x0065FDE4
0x0065FDE8 0x0065FDEC 0x0065FDF0 0x0065FDF4
----------------------------------------------------------------------------------
0x0065FDC8 0x0065FDCC 0x0065FDD0 0x0065FDD4
0x0065FDD8 0x0065FDDC 0x0065FDE0 0x0065FDE4
0x0065FDE8 0x0065FDEC 0x0065FDF0 0x0065FDF4
输出b数组每个元素的值:
12 36 62 56
98 63 56 99
88 32 66 22
--------------------------
12 36 62 56
98 63 56 99
88 32 66 22
pp是指针变量,可以进行自增运算。p是指针数组名(是地址常量),不能进行自增运算。对于二级指针pp,可以使用它的指针形式或下标形式对数组元素进行访问。
原文出处:
<数据类型> **<变量名>
两个符号**表示后面声明的变量为指向指针的指针变量。
例如,有如下声明语句:
int x=32;
int *p=&x;
int **pp=&p;
则x、p和pp三者之间的关系如图8-4所示。
指针变量p是一级指针,它指向x;指针变量pp是二级指针,它指向p。通过p和pp都可以访问x。*pp表示它所指向变量p的值,即x的地址;**pp表示它所指向的变量p所指向变量的值,即x的值。
指向指针的指针变量多用于访问二维数组。
例8-9 阅读下列程序,写出运行结果。
#include <iostream.h>
void main()
{int b[3][4]={12,36,62,56,98,63,56,99,88,32,66,22};
int *p[3]={b[0],b[1],b[2]};
int **pp=p;
int i,j;
cout<<"输出b数组每行的首地址:/n";
for(i=0;i<3;i++)
cout<<*pp++<<" ";
cout<<endl;
for(i=0;i<40;i++) cout<<"-";cout<<endl;
pp=p;
for(i=0;i<3;i++)
cout<<pp[i]<<" ";
cout<<endl;
for(i=0;i<40;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
cout<<p[i]<<" ";
cout<<endl;
cout<<"输出b数组每个元素的地址:/n";
for(i=0;i<3;i++)
{for(j=0;j<4;j++)
cout<<*(pp+i)+j<<" ";
cout<<endl;
}
for(i=0;i<50;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
{for(j=0;j<4;j++)
cout<<p[i]+j<<" ";
cout<<endl;
}
cout<<"输出b数组每个元素的值:/n";
for(i=0;i<3;i++)
{for(j=0;j<4;j++)
cout<<*(*(pp+i)+j)<<" ";
cout<<endl;
}
for(i=0;i<20;i++) cout<<"-";cout<<endl;
for(i=0;i<3;i++)
{for(j=0;j<4;j++)
cout<<p[i][j]<<" ";
cout<<endl;
}
}
程序运行的结果为:
输出b数组每行的首地址:
0x0065FDC8 0x0065FDD8 0x0065FDE8
-------------------------------------------------------------
0x0065FDC8 0x0065FDD8 0x0065FDE8
-------------------------------------------------------------
0x0065FDC8 0x0065FDD8 0x0065FDE8
输出b数组每个元素的地址:
0x0065FDC8 0x0065FDCC 0x0065FDD0 0x0065FDD4
0x0065FDD8 0x0065FDDC 0x0065FDE0 0x0065FDE4
0x0065FDE8 0x0065FDEC 0x0065FDF0 0x0065FDF4
----------------------------------------------------------------------------------
0x0065FDC8 0x0065FDCC 0x0065FDD0 0x0065FDD4
0x0065FDD8 0x0065FDDC 0x0065FDE0 0x0065FDE4
0x0065FDE8 0x0065FDEC 0x0065FDF0 0x0065FDF4
输出b数组每个元素的值:
12 36 62 56
98 63 56 99
88 32 66 22
--------------------------
12 36 62 56
98 63 56 99
88 32 66 22
pp是指针变量,可以进行自增运算。p是指针数组名(是地址常量),不能进行自增运算。对于二级指针pp,可以使用它的指针形式或下标形式对数组元素进行访问。
原文出处: