華爲代碼質量軍規 (1) 數組訪問,必須進行越界保護

https://blog.csdn.net/thecoldone/article/details/50759044編程

 

C++中數組做爲形參傳遞給函數時把數組視爲指針,並無將數組的長度信息傳遞給函數,於是在函數中稍有不慎就會形成數組內存的越界訪問。爲了不這個問題,下面根據書上給的內容作了一點總結和說明。數組

數組形參的定義函數

void func(int *) {/* ...*/}spa

void func(int[]) {/* ... */}.net

void func(int[10]) {/* ...*/}指針

上面三種形參表示方式都是合法和等價的,能夠看到C++將數組視爲指針。另外第三種表示方式看上去在方括號中用一個常量指定了數組的長度,但事實上編譯器忽略了這一方式指定的數組長度,在函數調用時即便你給func函數傳遞一個長度不爲10的數組編譯器一樣可讓你經過,只不過這在實際運行中可能形成數組內存的越界訪問。(注:這種表示方式要和下面介紹的數組引用相區分開來)code

由於C++並不支持將數組的長度信息自動傳遞給函數,因此咱們在編寫代碼時必須採起措施來避免數組形參帶來的越界訪問問題,下面給出幾種方法blog

1.顯示傳遞數組長度:在函數定義的參數列表中加多一個表示數組大小的參數,這種作法比較常見,舉個例子:內存

void func(int arr[], size_t size)
{
    for (size_t i = 0; i < size; i++)
        // operation
}

 

2.顯示指定數組開始和結束的位置:這種編程風格由標準庫所使用的技術啓發而得,常見於迭代器的使用,舉個例子:字符串

void func(int *begin, int *end)
{
    for (int *pt = begin; pt != end; pt++)
        // operation
}

 

3.顯示添加結束的標記:在數組末尾加多一個標識元素用來檢測數組的結束,常見的例子是C風格字符串,它是一種字符數組,而且以空字符null做爲結束的標記

void func(char *cstr)
{
    for (int i = 0; '\0' != cstr[i]; i++)
        // operation
}

 

4.經過引用傳遞數組:若是形參是數組的引用,編譯器不會將數組實參轉化爲指針,而是傳遞數組的引用自己

void func(int (&arr)[10])
{
    for (int i = 0; i < 10; i++)
        // operation
}
 
int main()
{
    int size = 20;
    int iarray[size] = {0};
    func(iarray); // error
    return 0;
}

不過這種方式編譯器有着嚴格的規定,使用時要注意如下幾點:

  • 實參和形參的數組的長度都必須是常量,包括字面值常量(例如上面的數字10)和const修飾的常量(const int Size = 20; void func(int (&arr)[Size]) { } ),例如上面在main函數中調用func函數錯誤的緣由在於實參數組iarray定義時用了變量size來指定長度。這樣作確保在編譯時就能檢測出可能出現的數組長度不一致的錯誤,而不至於等到運行時形成更嚴重的後果
  • 函數定義時&和變量名要用括號括起來,表示變量arr是指向int[10]型數組的指針
  • C++中的引用時容許修改原始數據,所以在函數調用時要謹慎考慮,若是不容許調用函數func對數組進行修改,在定義func函數時使用const修飾數組( void func(const int (&arr)[10]) )
相關文章
相關標籤/搜索