數組越界怎么處理 數組越界( 三 )


19 {
20 printf("b[%d]=%d ",j,b[j]);
21 }
22 printf("\nc[MAX2]:\n");
23 for(z=0;z<MAX2;z++)
24 {
25 printf("c[%d]=%d ",z,c[z]);
26 }
27 printf("\n");
28 return 0;
29}
運行結果為:
1 a[MAX]:
2 a[0]=1 a[1]=2 a[2]=3 a[3]=4 a[4]=5 a[5]=6 a[6]=7 a[7]=8 a[8]=9 a[9]=10
3 b[MAX1]:
4 b[0]=1 b[1]=2 b[2]=3 b[3]=4 b[4]=5 b[5]=0 b[6]=0 b[7]=0 b[8]=0 b[9]=0 b[10]=6 b[11]=7 b[12]=8 b[13]=9 b[14]=10
5 c[MAX2]:
6 c[0]=1 c[1]=6 c[2]=7 c[3]=8 c[4]=9 c[5]=10
對數組做越界檢查,確保索引值位于合法的范圍之內
要避免數組越界,除了上面所闡述的顯式指定數組的邊界之外,還可以在數組使用之前進行越界檢查,檢查數組的界限和字符串(也以數組的方式存放)的結束,以保證數組索引值位于合法的范圍之內 。例如,在寫處理數組的函數時,一般應該有一個范圍參數;在處理字符串時總檢查是否遇到空字符‘\0’ 。
來看下面一段代碼示例:
1#define ARRAY_NUM 10
2int *TestArray(int num,int value)
3{
4 int *arr=NULL;
5 arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
6 if(arr!=NULL)
7 {
8 arr[num]=value;
9 }
10 else
11 {
12 /*處理arr==NULL*/
13 }
14 return arr;
15}
從上面的int*TestArray(int num,int value)函數中不難看出,其中存在著一個很明顯的問題,那就是無法保證 num 參數是否越界(即當num>=ARRAY_NUM的情況) 。因此,應該對 num 參數進行越界檢查,示例代碼如下所示:
1int *TestArray(int num,int value)
2{
3 int *arr=NULL;
4 /*越界檢查(越上界)*/
5 if(num<ARRAY_NUM)
6 {
7 arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
8 if(arr!=NULL)
9 {
10 arr[num]=value;
11 }
12 else
13 {
14 /*處理arr==NULL*/
15 }
16 }
17 return arr;
18}
這樣通過if(num<ARRAY_NUM)語句進行越界檢查,從而保證 num 參數沒有越過這個數組的上界 ?,F在看起來,TestArray() 函數應該沒什么問題,也不會發生什么越界錯誤 。

數組越界怎么處理  數組越界

文章插圖

但是,如果仔細檢查,TestArray() 函數仍然還存在一個致命的問題,那就是沒有檢查數組的下界 。由于這里的 num 參數類型是 int 類型,因此可能為負數 。如果 num 參數所傳遞的值為負數,將導致在 arr 所引用的內存邊界之外進行寫入 。
當然,你可以通過向if(num<ARRAY_NUM)語句里面再加一個條件進行測試,如下面的代碼所示:
if(num>=0&&num<ARRAY_NUM)
{
}
但是,這樣的函數形式對調用者來說是不友好的(由于 int 類型的原因,對調用者來說仍然可以傳遞負數,至于在函數中怎么處理那是另外一件事情),因此,更佳的解決方案是將 num 參數聲明為 size_t 類型,從根本上防止它傳遞負數,示例代碼如下所示:
1int *TestArray(size_t num,int value)
2{
3 int *arr=NULL;
4 /*越界檢查(越上界)*/
5 if(num<ARRAY_NUM)
6 {
7 arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
8 if(arr!=NULL)
9 {
10 arr[num]=value;
11 }
12 else
13 {
14 /*處理arr==NULL*/
15 }
16 }
17 return arr;
18}
獲取數組的長度時不要對指針應用 sizeof 操作符
在 C 語言中,sizeof 這個其貌不揚的家伙經常會讓無數程序員叫苦連連 。同時,它也是各大公司爭相選用的面試必備題目 。簡單地講,sizeof 是一個單目操作符,不是函數 。其作用就是返回一個操作數所占的內存字節數 。其中,操作數可以是一個表達式或括在括號內的類型名,操作數的存儲大小由操作數的類型來決定 。例如,對于數組int a[5],可以使用sizeof(a)來獲取數組的長度,使用sizeof(a[0])來獲取數組元素的長度 。
但需要注意的是,sizeof 操作符不能用于函數類型、不完全類型(指具有未知存儲大小的數據類型,如未知存儲大小的數組類型、未知內容的結構或聯合類型、void 類型等)與位字段 。例如,以下都是不正確形式:
1/*若此時max定義為intmax();*/
2sizeof(max)
3/*若此時arr定義為char arr[MAX],且MAX未知*/
4sizeof(arr)
5/*不能夠用于void類型*/
6sizeof(void)
7/*不能夠用于位字段*/
8struct S
9{
10 unsigned int f1 : 1;
11 unsigned int f2 : 5;
12 unsigned int f3 : 12;
13};
14sizeof(S.f1);
了解 sizeof 操作符之后,現在來看下面的示例代碼:

推薦閱讀