1.定义指针数组
一个数组中若每个元素都是一个指针,则为指针数组。
例如,下面的代码定义一个字符指针数组,并对其初始化:
char*
proname()={"Fortran",
"C",
"C++"};
该指针数组具有变量属性,所以可以是全局的、静态的和局部的。
proname数组中每个元素都存放一个字符指针(char*),初始化中的每个值都是一个字符串常量,这些常量存储在内存data区的const子区中,
而不管proname是全局还是局部变量。字符串常量在const子区中有可能连续分布,也可能不是,但这无关紧要,重要的是指向这些字符串的指针是连续排列在指针数组中的。在16位机器中,
proname数组空间占6个字节以存放3个字符指针,见图8-12。
图8-12 字符数组的内存表示
2.指针数组与二维数组
指针数组与二维数组是有区别的。前面看到字符指针数组的内存表示,指针所指向的字符串是不规则长度的。
proname数组本身含有6个字节(假设每个指针占2个字节);
proname[0]指向的字符串长8个字节(包括,'\0');
proname[1]指向的字符串长2个字节;
proname[2]指向的字符串长4个字节;
Droname所占内存总数为20个字节。
使用二维数组时的情况:
char
name[3][8]={"Fortran","C","C++"};
在二维数组情况下,每一列的大小必须是一样的,因此只能将数组中所要存的字符串中最长列的大小作为数组的列的大小。这样,共需3*8=24字节。
3.指向指针的指针
指针数组是数组,是数组则其名字便为指针常量。指针具有类型,那么指针数组名是什么类型呢?
指针数组名是指向指针的指针(即二级指针)。
例如,下面的代码描述了指向字符指针的指针:
char* pc[]={"a","b","c"};
char* *ppc;
ppc=pc;
//ok
这里的初始化值"a","b","c"必须为双引号,
如果单引号则表示字符而不是字符串,字符没有'\0'的结束标记。字符总是占一个字节。
传递数组给函数就是传递指针给函数。传递指针数组给函数就是传递二级指针给函数。
例如,下面的程序把一个字符指针数组传递给函数:
//**********************
//** ch8_20.cpp
**
//**********************
#include
void Print(char*[],int);
void
main()
{
char*
pn[]={"Fred","Barney","Wilma","Betty"};
int num
=sizeof(pn)/sizeof(char*);//获取指针数组长度
Print(pn,num);
}
void
Print(char* arr[], int len)
{
for(int i=0; i cout <<(int)arr[i] <<" " //输出字符串地址
< }
运行结果为:
4202628
Fred
4202633 Barney
4202640 wilma
4202646
Betty
arr是指向字符指针的指针,所以*arr是字符指针,*(arr+i)是arr开始的第i个字符指针,*(arr+i)就是arr[i]。
arr是指针而不是数组,尽管形参声明为指针数组。
这是由传递数组参数即为指针的特性决定的。所以,函数的输出语句可以写为:
cout<<(int)*
arr;
cout<<*arr++ < 输出字符指针就是输出字符串。如果要输出字符指针的地址值,应该将字符指针强制转换为整型:“cout<<(int)arr[i];”。
例中输出的地址是10进制表示的整数。若要以16进制表示输出,则须用流控制的方法实现。
传递字符指针的指针之内存布局见图8—13。
图8-13 传递字符指针的指针之内存布局
4.NULL指针值
NULL是空指针值,它不指向任何地方。不同的操作系统,会使编译取不同的NULL值。因此,NULL是个不确定值。
在PC中的BC和VC,NULL都取0值。如果严格考虑到移植,那么不应养成NULL即为0的习惯。
,
例如,下面的代码可移植性差:
char ch=NULL; //NULL是个不确定值
char *pc=NULL;
//ok:将空指针值赋给pc
在程序中,如果一个数组大小不定,则处理指针数组时可以利用在数组末尾设置NULL来解决。
例如,下面的程序通过对ch8_20.cpp中的指针数组设置NULL的方法进行处理:
//**********************
//**
ch8_21.cpp **
//**********************
#include
void Print(char*[]);
void main()
{
char*
pn[]={"Fred","Barney","Wilma","Betty",NULL};
Print(pn);
}
void Print(char* arr[])
{
while(*arr!=NULL){
//输出各字符串
cout <<(int)*arr <<" "
<<*arr
< arr++;
}
}
运行结果为:
4202628 Fred
4202633
Barney
4202640 wilma
4202646 Betty
在主函数传递数组参数给Pnnt()函数时,并不需要将数组元素个数传递过去,因为程序中函数之间达成了一种默契:遇到NULL空指针就结束数组处理。
NULL与void*是不同的概念,
NULL是一个值,一个指针值,任何类型的指针都可赋予该值。而void*是一种类型,是一种无任何类型的指针。