华为代码质量军规 (1) 数组访问,必须进行越界保护
https://blog.csdn.net/thecoldone/article/details/50759044
?
C++中數組作為形參傳遞給函數時把數組視為指針,并沒有將數組的長度信息傳遞給函數,因而在函數中稍有不慎就會造成數組內存的越界訪問。為了避免這個問題,下面根據書上給的內容做了一點總結和說明。
數組形參的定義
void func(int *) {/* ...*/}
void func(int[]) {/* ... */}
void func(int[10]) {/* ...*/}
上面三種形參表示方式都是合法和等價的,可以看到C++將數組視為指針。另外第三種表示方式看上去在方括號中用一個常量指定了數組的長度,但事實上編譯器忽略了這一方式指定的數組長度,在函數調用時即使你給func函數傳遞一個長度不為10的數組編譯器同樣可以讓你通過,只不過這在實際運行中可能造成數組內存的越界訪問。(注:這種表示方式要和下面介紹的數組引用相區分開來)
因為C++并不支持將數組的長度信息自動傳遞給函數,所以我們在編寫代碼時必須采取措施來避免數組形參帶來的越界訪問問題,下面給出幾種方法
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); // errorreturn 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]) )
轉載于:https://www.cnblogs.com/ye-ming/p/9598799.html
總結
以上是生活随笔為你收集整理的华为代码质量军规 (1) 数组访问,必须进行越界保护的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pythonのgevent同步异步区别
- 下一篇: python全栈开发第36天------