》指 针
即指针变量,与其他类型变量一样,指针变量也必须要先声明。一般形式:
<数据类型> *<变量名>;
其中,<数据类型>是指针所指对象的类型,在C++中指针可以指向任何C++类型。<变量名>是指针变量名。
指针使用两种特殊的运算符 *和&。
一元(单目)运算符&用于返回其操作对象的内存地址,其操作对象通常为一个变量名。
例:ptr=&total;
把变量total的内存地址存到指针变量ptr中。该地址是total变量在计算机内存中的存储地址。
* 运算符它与 & 运算符作用相反。作为意愿运算符的*用于返回其操作数所指对象的值,因此,该运算符要求其操作对象为一个指针。
>指针说明
int *ptr; //指向整型量的指针
char *ptr; //指向字符型的指针
char *acp[10]; //由指向字符的指针构成的数组,即指针数组
char( *pac)[10]; //指向字符数组的指针,即数组指针
int f( ); //返回值为整型量的函数
int *fpi( ); //返回值为指向整型量的指针的函数,即指针函数
int(*pfi)( ); //指向返回值为整型量的函数的指针,即函数指针
int(*p[4][3])( ); //指针数组,数组中每个元素为指向返回值为整型量的函数的指针
int *(*pfpi)( ); //指向函数的指针,该函数的返回值为指向整型量的指针
注:在使用任何指针变量之前必须先给它赋一个指向合法具体对象的地址值。
常见错误:
int x=1; int *px; *px=x;
在此,在给*px赋值前,指针变量px并没有指向一个具体对象。由于px中有一个随机值,该赋值将破坏内存中某个地址空间中的内容,严重时将导致程序挂起或机器死机。
char *s; cin>>s;
因为指针s并没有指向一个具体对象(空间),因此无法存储所读入的字符串(将破坏内存中某段空间的内容)。
使一个指针指向一个具体对象的方法:
> 使用new运算符(或malloc和alloc等函数) 给指针分配一个具体空间。
>将另一个同类型的指针赋给它以获得值。
>通过&运算符指向某个对象。
>指针运算
尽管指针中存放的是变量的地址,但在C++中指针只能进行如下运算。
(1)指针和整型量可以进行加减 若p为指针,n为整型量,则p+n和p-n是合法的,同样p++也是合法的,它们的结果同指针所指对象类型相关。如若p为指向字符数组的指针,则p+1为指向字符数组下一个元素的指针(假如p指向字符数组的第一个元素,则p+1指向数组的第二个元素),实际增加1;若p为指向整型数组的指针,则p+1指向整型数组的下一个元素的指针,实际增加1个整型单位长(假如int类型长度为32位,则实际增加4个字节,可用sizeof运算符计算某个类型的长度)。
(2)若p1、p2为指针,当p1和p2指向同一类型时,可以进行赋值。如:p1=p2;
注:该语句使得两指针p1和p2指向同一空间,若其中一个指针所指空间被删除(释放),则另一个指针所指空间也会被释放,这就是指针悬挂的问题。
(3)两个指向同一类型的指针,可进行==,>,<等关系运算,其实就是地址的比较。
假如p指向数组的第一个元素,q指向数组的第二个元素,则表达式p<q为真。例:利用两个指针的比较,颠倒字符串中字符的首尾位置。
void reverse(char *s)
{
char *p,*q,temp;
p=s; //p指向字符串s的第一个字符
q=s+strlen(s)-1; //q指向字符串s的最后一个字符
while(p<q)
{
temp=*p;
*p=*q;
*q=temp;
p++;q--;
}
}
(4)两个指向同一数组成员的指针可进行相减,结果为两个指针之间相差元素的个数。
例:假设p指向数组头,q指向数组尾,则q-p+1表示数组长度 注:两指针不能相加。
用指针计算中间指针的值的方法是:mid=low+(high-low)/2; 这与数组中情况是不同的,在数组中,在已知两个数组下标的情况下,可用mid=(low+high)/2这种方法来计算中间元素的下标,如在数组中进行折半查找(二分查找)时,即采用这种方法。
(5)几组常见的指针运算表达式比较
>p++和p+1的区别 指针p++的结果为p指向下一元素;p+1结果为下一元素的指针,但p本身不变。
>y=*px+1和y=*(px+1)的区别 *px+1结果为取px所指对象内容加1;*(px+1)结果为px指针加1,并取结果指针所指对象内容。
>y=(*px)++和y=*px++的区别 (*px)++为先取指针px所指对象内容进行运算(因为运算符++为后置运算),然后对指针px所指对象内容加1;*px++为先取指针px所指对象内容进行运算,然后指针px加1。
例:px->100; 则y=(*px)++=100,px->101; 则y=*px++=100,px指向数组的下一个元素。
>指针和数组
在C++中,指针和数组的关系极为密切。实际上,数组的参数传递、数组元素的存取,都可通过指针操作来完成。指针和数组常常可以互换。
在C++中,数组的名字就是指向该数组第一个元素(下标为0)的指针,即该数组第一个元素的地址,也即数组的首地址。一般情况下,一个数组元素的下标访问a[i]等价于相应的指针访问*(a+i)。但要特别注意:数组名和指针(变量)是有区别的,前者是常量,即数组名是一个常量指针,而后者是指针变量。
例:int a[10],*pa; 尽管可以写pa=a;但是不能写:a=pa;或a++;或pa=&a;因为我们不能改变常量的值,也不能取常量的地址。
数组名可作为参数进行传递。当将数组名传给函数时,实际上传递的是数组的开始地址(即数组第一个元素的地址)。使用指针的原因是因为指针运算比数组运算速度快。此外,使用指针的另一个原因是在大量数据传递时,传递指针要远比传递数据本身效率高的多,如在函数参数传递及函数返回值时。
对于字符串常量,可以把它看成是一个无名字符数组,C++编译程序会自动为它分配一个空间来存放这个常量,字符串常量的值本身就是指向这个无名字符数组的第一个字符的指针,其类型是字符指针。
注:字符数组和字符指针使用时容易混淆。例:
char *char_ptr,word[20];
char_ptr="point to me"; //正确,把字符串常量第一个字符指针赋给字符指针变量char_ptr
word="you can`t do this"; //错误,数组名word是常量,不能改变一个常量的值
假设:int values[100],*intptr=values,i;下表归纳了指向数组的指针和数组之间的各种关系,数组方式表示比用指针方式表示具有更好的可读性。