資料結構與演算法之美
在看極客時間的專欄的時候遇到了一個很有趣的問題:
想一下以下的程式碼執行之後答案為多少?
int main(int argc, char* argv[]){
int i = 0;
int arr[3] = {0};
for(; i<=3; i++){
arr[i] = 0;
printf("hello world\n");
}
return 0;
}
按照正常的思維大概是輸出三次hello world之後便停止,但是結果並非如此。
放到編譯器跑一下之後發現是無限迴圈的列印,這是為什麼呢?
我們知道,在C語言中,只要不是訪問受限的記憶體,所有的記憶體空間都是可以自由訪問的。a[3]也會被定位到某塊不屬於陣列的記憶體地址上,而這個地址正好是儲存變數i的記憶體地址,那麼a[3]=0就相當於i=0,所以就會導致程式碼無限迴圈。
這個與定義的順序有關,如果在i和陣列的定義中間插入一個其他的定義則不會出現這種情況,這又是為什麼呢?
因為在作業系統中函式體內的區域性變數存在棧上,且是連續壓棧。在Linux程式的記憶體佈局中,棧區在高地址空間,從高向低增長。變數i和arr在相鄰地址,且i比arr的地址大,所以arr越界正好訪問到i。當然,前提是i和arr元素同型別,否則那段程式碼仍是未決行為。
需要額外注意的是:
例子中死迴圈的問題跟編譯器分配記憶體和位元組對齊有關 陣列3個元素 加上一個變數a 。4個整數剛好能滿足8位元組對齊 所以i的地址恰好跟著a2後面 導致死迴圈。。如果陣列本身有4個元素 則這裡不會出現死迴圈。。因為編譯器64位作業系統下 預設會進行8位元組對齊 變數i的地址就不緊跟著陣列後面了(64位中一個int佔32位,也就是四個位元組,讀取的時候最後陣列中的位元組和定義的整數正好組成了一個8位元組,則產生了無線列印)
相關文章
- 《資料結構與演算法之美》資料結構與演算法學習書單 (讀後感)資料結構演算法
- 《資料結構與演算法之美》學習筆記之開篇資料結構演算法筆記
- 資料結構與演算法之線性結構資料結構演算法
- 演算法與資料結構之集合演算法資料結構
- 資料結構與演算法之排序資料結構演算法排序
- 資料結構與演算法之美-王爭-極客時間資料結構演算法
- 資料結構與演算法之美-02複雜度分析(下)資料結構演算法複雜度
- 《資料結構與演算法之美》為什麼要學習資料結構和演算法 (讀後感)資料結構演算法
- 《資料結構與演算法之美》學習筆記之複雜度資料結構演算法筆記複雜度
- 《資料結構與演算法之美》如何抓住重點,系統高效地學習資料結構與演算法 (讀後感)資料結構演算法
- 陣列(Array)- 極客時間(資料結構與演算法之美)陣列資料結構演算法
- python之資料結構與演算法分析Python資料結構演算法
- 資料結構與演算法之快速排序資料結構演算法排序
- JavaScript 資料結構與演算法之美 - 十大經典排序演算法JavaScript資料結構演算法排序
- 資料結構與演算法-資料結構(棧)資料結構演算法
- 演算法與資料結構之並查集演算法資料結構並查集
- 04 Javascript資料結構與演算法 之 集合JavaScript資料結構演算法
- 演算法與資料結構之原地堆排序演算法資料結構排序
- 05 Javascript資料結構與演算法 之 樹JavaScript資料結構演算法
- 06 Javascript資料結構與演算法 之 圖JavaScript資料結構演算法
- 資料結構與演算法之稀疏陣列資料結構演算法陣列
- 03 Javascript資料結構與演算法 之 連結串列JavaScript資料結構演算法
- 07 Javascript資料結構與演算法 之 排序演算法JavaScript資料結構演算法排序
- JavaScript 資料結構與演算法之美 - 時間和空間複雜度JavaScript資料結構演算法複雜度
- 資料結構與演算法資料結構演算法
- 資料結構:初識(資料結構、演算法與演算法分析)資料結構演算法
- 01Javascript資料結構與演算法 之 棧JavaScript資料結構演算法
- 資料結構與演算法之基礎知識資料結構演算法
- 資料結構與演算法:圖形結構資料結構演算法
- 演算法與資料結構之圖的表示與遍歷演算法資料結構
- python演算法與資料結構-什麼是資料結構Python演算法資料結構
- 資料結構與演算法02資料結構演算法
- 資料結構與演算法-堆資料結構演算法
- 資料結構與演算法03資料結構演算法
- 【JavaScript 演算法與資料結構】JavaScript演算法資料結構
- 資料結構與演算法(java)資料結構演算法Java
- python資料結構與演算法Python資料結構演算法
- 資料結構與演算法——字串資料結構演算法字串