指針可以加上或減去一個(gè)整數(shù)。指針的這種運(yùn)算的意義和通常的數(shù)值的加減
運(yùn)算的意義是不一樣的,以單元為單位。例如:
例二:
char a[20];
int *ptr=(int *)a; //強(qiáng)制類型轉(zhuǎn)換并不會(huì)改變a 的類型
ptr++;
在上例中,指針ptr 的類型是int*,它指向的類型是int,它被初始化
為指向整型變量a。接下來的第3 句中,指針ptr 被加了1,編譯器是這樣
處理的:它把指針ptr 的值加上了sizeof(int),在32 位程序中,是被加上
了4,因?yàn)樵?2 位程序中,int 占4 個(gè)字節(jié)。由于地址是用字節(jié)做單位的,
故ptr 所指向的地址由原來的變量a 的地址向高地址方向增加了4 個(gè)字節(jié)。
由于char 類型的長(zhǎng)度是一個(gè)字節(jié),所以,原來ptr 是指向數(shù)組a 的第0 號(hào)
單元開始的四個(gè)字節(jié),此時(shí)指向了數(shù)組a 中從第4 號(hào)單元開始的四個(gè)字節(jié)。
我們可以用一個(gè)指針和一個(gè)循環(huán)來遍歷一個(gè)數(shù)組,看例子:
例三:
int array[20]={0};
int *ptr=array;
for(i=0;i<20;i++)
{
(*ptr)++;
ptr++;
}
這個(gè)例子將整型數(shù)組中各個(gè)單元的值加1。由于每次循環(huán)都將指針ptr
加1 個(gè)單元,所以每次循環(huán)都能訪問數(shù)組的下一個(gè)單元。
再看例子:
例四:
char a[20]="You_are_a_girl";
int *ptr=(int *)a;
ptr+=5;
在這個(gè)例子中,ptr 被加上了5,編譯器是這樣處理的:將指針ptr 的
值加上5 乘sizeof(int),在32 位程序中就是加上了5 乘4=20。由于地址
的單位是字節(jié),故現(xiàn)在的ptr 所指向的地址比起加5 后的ptr 所指向的地址
來說,向高地址方向移動(dòng)了20 個(gè)字節(jié)。在這個(gè)例子中,沒加5 前的ptr 指
向數(shù)組a 的第0 號(hào)單元開始的四個(gè)字節(jié),加5 后,ptr 已經(jīng)指向了數(shù)組a 的
合法范圍之外了。雖然這種情況在應(yīng)用上會(huì)出問題,但在語法上卻是可以的。
這也體現(xiàn)出了指針的靈活性。
如果上例中,ptr 是被減去5,那么處理過程大同小異,只不過ptr 的
值是被減去5 乘sizeof(int),新的ptr 指向的地址將比原來的ptr 所指向
的地址向低地址方向移動(dòng)了20 個(gè)字節(jié)。
下面請(qǐng)?jiān)试S我再舉一個(gè)例子:(一個(gè)誤區(qū))
例五:
#include<stdio.h>
int main()
{
char a[20]=" You_are_a_girl";
char *p=a;
char **ptr=&p;
//printf("p=%d\n",p);
//printf("ptr=%d\n",ptr);
//printf("*ptr=%d\n",*ptr);
printf("**ptr=%c\n",**ptr);
ptr++;
//printf("ptr=%d\n",ptr);
//printf("*ptr=%d\n",*ptr);
printf("**ptr=%c\n",**ptr);
}
誤區(qū)一、輸出答案為Y 和o
誤解:ptr 是一個(gè)char 的二級(jí)指針,當(dāng)執(zhí)行ptr++;時(shí),會(huì)使指針加一個(gè)
sizeof(char),所以輸出如上結(jié)果,這個(gè)可能只是少部分人的結(jié)果.
誤區(qū)二、輸出答案為Y 和a
誤解:ptr 指向的是一個(gè)char *類型,當(dāng)執(zhí)行ptr++;時(shí),會(huì)使指針加一個(gè)
sizeof(char *)(有可能會(huì)有人認(rèn)為這個(gè)值為1,那就會(huì)得到誤區(qū)一的答
案,這個(gè)值應(yīng)該是4,參考前面內(nèi)容), 即&p+4; 那進(jìn)行一次取值運(yùn)算不
就指向數(shù)組中的第五個(gè)元素了嗎?那輸出的結(jié)果不就是數(shù)組中第五個(gè)元
素了嗎?答案是否定的.
正解: ptr 的類型是char **,指向的類型是一個(gè)char *類型,該指向的
地址就是p的地址(&p),當(dāng)執(zhí)行ptr++;時(shí),會(huì)使指針加一個(gè)sizeof(char
*),即&p+4;那*(&p+4)指向哪呢,這個(gè)你去問上帝吧,或者他會(huì)告訴你在
哪?所以最后的輸出會(huì)是一個(gè)隨機(jī)的值,或許是一個(gè)非法操作.
總結(jié)一下:
一個(gè)指針ptrold 加(減)一個(gè)整數(shù)n 后,結(jié)果是一個(gè)新的指針ptrnew,
ptrnew 的類型和ptrold 的類型相同,ptrnew 所指向的類型和ptrold
所指向的類型也相同。ptrnew 的值將比ptrold 的值增加(減少)了n 乘
sizeof(ptrold 所指向的類型)個(gè)字節(jié)。就是說,ptrnew 所指向的內(nèi)存
區(qū)將比ptrold 所指向的內(nèi)存區(qū)向高(低)地址方向移動(dòng)了n 乘
sizeof(ptrold 所指向的類型)個(gè)字節(jié)。
指針和指針進(jìn)行加減:
兩個(gè)指針不能進(jìn)行加法運(yùn)算,這是非法操作,因?yàn)檫M(jìn)行加法后,得到的
結(jié)果指向一個(gè)不知所向的地方,而且毫無意義。兩個(gè)指針可以進(jìn)行減法
操作,但必須類型相同,一般用在數(shù)組方面,不多說了。