一、指針的移動
1.1 指針的向前及向后移動
指針每次加一就是指針向前移動指針類型對應的字節數。下面通過一個int指針來指向一個int數組,看看指針的加法運算到底是個什么鬼?
int nums[]={33,55,77,88,99}; int* ptr = nums; printf("%d\n",*ptr); ptr++; // ptr是int類型的指針,所以向后移動4個字節 printf("%d\n",*ptr); ptr+=2; // 向后移動2*4 個字節 printf("%d\n",*ptr);
運行結果如下圖所示:
可以看到,指針的加法就是向前移動指定類型字節數,在數組中就是指向下一個元素。
下面再來看看與加法相反的減法,仍然以上面的代碼為例,新增一句:ptr--;
int nums[]={33,55,77,88,99}; int* ptr = nums; printf("%d\n",*ptr); ptr++; // ptr是int類型的指針,所以向后移動4個字節 printf("%d\n",*ptr); ptr+=2; // 向后移動2*4 個字節 printf("%d\n",*ptr); ptr--; printf("%d\n",*ptr);
運行結果如下圖所示:
可以看出,減法即代表向后移動指針類型對應的字節數。
1.2 char類型指針的移動
對於char類型的指針移動,實際就是指向下一個字符或上一個字符:
char s1[]="hello edisonchou.cn"; char* p=s1; p=p+2; // char類型占一個字節,因此這里向后移動2*1個字節 printf("%s\n",s1); printf("%s\n",p);
這里實現了一個類似於求子串的操作,運行結果如下圖所示:
1.3 同類型指針的相減
同類型指針相減,得出的是相距的數據類型的長度。下面以兩個指向同一個int數組的int類型指針為例,驗證一下是否得到相距的數據類型的長度:
int nums[]={33,44,55,66,77}; int* iP1=nums; int* iP2=nums; iP2=iP2+3; // 同類型指針相減得出的是相距的數據類型的長度 printf("The distance is %d\n",iP2-iP1);
當iP2-iP3得到的是距離是3,這是因為iP2在進行減法操作之前已經向前移動了3個int類型的長度。
二、指針強大但又危險
2.1 從你家到他家
剛剛了解了指針的移動的強大,現在我們來看看指針的強大所帶來的一些“危險”。例如下面一段代碼,我們定義了兩個int類型的整數。
int i1=555; int i2=666; int* p=&i1; printf("%d,%d\n",&i1,&i2); p--; int i3=*p; //從p當前指向的內存中取出4個字節,解釋成i3 printf("%d\n",i3);
在指針p的定義中,我們指向的是i1。而當我們對p指針進行減法運算移動時,我們發現當前p指針指向的居然不是i1而是i2了。這也就說明,本來聲明指針時指向的是你家的地址,而當對指針進行運算操作后卻指向了隔壁老王家的地址,這是搞什么鬼!
可以從運行結果圖看出,i1和i2的地址分別為2686740和2686736(是連續的地址),p指針最開始指向的是i1。而當p向后移動之后,此時已經指向了i2。因此,輸出的值為666。
2.2 內存訪問越界
繼續上面的例子,我們此時再將p指針向后移動,看看此時p指針所指向的內容的值是多少?當我們再把p指針向后移動99999位時,其所指向的內容的值又是多少?
int i1=555; int i2=666; int* p=&i1; printf("%d,%d\n",&i1,&i2); p--; int i3=*p; //從p當前指向的內存中取出4個字節,解釋成i3 printf("%d\n",i3); p--; printf("%d\n",*p);
當運行程序后,結果變為了下圖:
那么,這個4200782地址是個什么鬼?它存放的又是什么內容?我們不得而知,這也是另一個程序里邊某個變量所存儲的位置,但現在在我們這個程序中居然通過指針訪問到了!這是個可怕的事情!想想,當A程序中的指針通過移動取得了B程序中的內存地址或數據內容,再對指針對其修改數據,這是一件不安全的事兒!想想一幫苦逼程序員辛辛苦苦加班加點做的游戲,輕而易舉地就被掛了外掛,本來需要用RMB才能買的積分或者道具讓外掛直接給改了,是不是覺得人生已經沒有意義啦?
下面一段代碼則展示了,當指針移動的距離過大時,Windows系統會對此訪問限制,程序直接報錯。
p-=99999; //這個內存地址可能是無法訪問的,又被稱為訪問越界 //Windows對此做了訪問越界的限制 printf("%d\n",*p);
運行結果是,直接崩潰,彈出錯誤按鈕:
錯誤框的出現,代表了指針使用不當的危害,會給客戶造成一定時間的延遲服務。因此,指針雖然很強大,但是也很危險!
參考資料
如鵬網,《C語言也能干大事(第三版)》