陣列越界問題和指標初入門例子分析
主要內容:陣列越界問題和指標初入門例子分析
一、 陣列越界問題
例子思考
int main()
{
int i;
int arr[10];
for(i=0;i<=10;i++)
{
arr[i] = 0;
printf("%d\n",i);
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
問題:當執行上述程式碼時,會出現什麼問題?為什麼會這樣?
為解決以上問題,我們首先得明白當定義一個函式時,函式中各個量的空間分配符合棧(後進先出)的原則,如果一個量被先定義,那麼系統便先給它分配儲存空間。而在陣列中,0號下標地址值永遠小於1號下標地址值。因此,對於上述問題,我們可以畫出它的記憶體空間示意圖,分析執行程式碼會出現什麼結果。具體圖如下所示:
根據上圖所示,程式從主函式開始往下執行,當int i;時,系統首先為i分配四個位元組的空間,接著int arr[10];時,定義了一個長度為10的陣列,因為在陣列中,0號下標地址值永遠小於1號下標地址值,同時棧的定義就是棧底地址大。便可知到上圖(左)(圖中兩紅線之間表示為陣列所佔空間)便為定義後,i與陣列arr在記憶體中分配圖。接著執行:for(i=0;i<=10;i++){arr[i] = 0; printf("%d\n",i);}。當i<10時,陣列下標0-9分別對應的元素被賦值為0。i=10時陣列滿溢,會發生越界情況。在陣列越界情況中,陣列會預設牽涉其鄰近元素,在此例子中即為i,因此當i=10時,系統會將i所對應的值賦為0。
結論
此段程式碼執行時會產生死迴圈。原因是:因為陣列越界,當i=10時,系統將i所對應的值賦為0,此時i=0且i<=10系統又會進入新一輪迴圈。以此類推,系統陷入死迴圈。
解決辦法
i.編譯器:Visual Studio 2012針對於上述問題會產生崩潰現象,具體實現過程如上圖(右),VS12會在陣列arr與變數i中間進行隔離,避免陣列越界影響到i,同時在陣列arr與變數i中間申請兩個記憶體空間,分別放在兩顆“炸彈”,陣列一旦越界,觸碰到炸彈,系統中斷,提出警告。
ii.人力控制:牢記陣列最大下標值=陣列長度-1,程式碼仔細書寫,避免越界問題產生。
二、 指標初入門
概念介紹
符號& :表示取地址。//eg: &a表示取a 的地址。
符號* :可以表示乘法、定義一個指標變數、對變數解引用。//eg: 34、intp(定義一個指標變數p)、*p(對p解引用)
首先我們得知道指標==地址 ,通過以下介紹,我們來理解指標為什麼相當於地址。
例子思考
其中&a=1000,&b=2000,&p=3000,觀察此程式碼,分析每一步都做了什麼!
int main()
{
int a = 10;
int b = 20;
int *p = &a;
*p = 100;
p = &b;
*p = 200;
int **pp = &p;
*pp = &a;
**pp = 1000;
*pp = &b;
**pp = 2000;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
對上段程式碼,我們畫圖理解:
(1)定義一個整形變數a,並將10賦值給它;
(2)定義一個整形變數b,並將20賦值給它;
(3)定義一個整形指標變數p儲存變數a的地址,此時執行上圖中的第(1) 步,p指向a;
(4)*p = 100;對p解一次引用,此時p指向a,即a=100;
(5)指標變數p儲存變數b的地址,此時執行上圖中的第(2) 步,p指向b;
(6)*p = 200;對p解一次引用,此時p指向b,即b=200;
(7)定義一個整形二級指標變數pp儲存指標變數p的地址;
(8)對pp解一次引用,也就是執行上圖中的第(3) 步,pp指向p,此時p中儲存的是a的地址,即p=&a;
(9)對pp解兩次引用,也就是執行上圖中的第(3) 步,再執行第(1) 步,pp指向p,此時pp指向a的值, **pp = 1000,也就是將a的值置為1000;
(10)對pp解一次引用,也就是執行上圖中的第(3) 步,pp指向p,此時將b的地址賦值給p,p中儲存的是b的地址,即p=&b;
(11)對pp解兩次引用,也就是執行上圖中的第(3) 步,再執行第(2) 步,pp指向p,此時pp指向b的值, **pp = 2000,也就是將b的值置為2000;
因此,此程式碼每一步都做了什麼展示如下:
int main()
{
int a = 10;(1)
int b = 20;(2)
int *p = &a;(3)
*p = 100;(4) //a = 100;
p = &b;(5)
*p = 200;(6) //b = 200;
int **pp = &p;(7)
*pp = &a; (8) //p = &a;
**pp = 1000; (9) //a = 1000;
*pp = &b;(10) //p = &b;
**pp = 2000;(11) //b = 2000;
return 0;
}
作者:du_lijun
來源:CSDN
原文:https://blog.csdn.net/du_lijun/article/details/83083317
版權宣告:本文為博主原創文章,轉載請附上博文連結!