memset 和 二維陣列之間個“隔閡”
前言:今天在做的題目之中 出現了一個十分有趣的現象 就是 使用memset中直接的問題。現在分享一下。
掉坑的題目 《1050 螺旋矩陣(25)(25 分)》
我們定義二維陣列不過是三種方法
1.直接定義法 int P[100][100];
2.malloc定義法 int** P = (int **)malloc(sizeof(int *)*100); for(int i=0;i<100;i++) P[i]=(int *)malloc(sizeof(int)*100);
3.calloc 定義法 int** P = (int **)calloc(100,sizeof(int *)); for(int i=0;i<100;i++) P[i]=(int *)calloc(100,sizeof(int));
有的人說了 malloc不是大致和calloc相同嗎? 但是有時候 一些細節就會讓你 好久都沒有辦法查的出來。比如我今天所說的memset的超級大坑。
為了掉進我設下的這個坑 我們 使用方法 2 開闢了空間 建立了二維陣列 。我們知道 使用malloc開闢的二維陣列每一個元素的值就像在區域性變數一樣都是隨機值。
這個時候 心大的同學就很想 使用 memset 來初始化這個“陣列”了 在我們的印象裡 我們初始化 使用 方法 1 定義的陣列的時候都是這樣的 (例如初始化為 0 ):memset(P,0,sizeof(P));
int P[100][100]; memset(P, 0, sizeof(P));
執行完成以後 通過編譯器的除錯框 我們可以看出 是初始化成功了
初始化前:
初始化後:
顯然是成功的。
但是 但是 但是 。 我們使用方法 2 定義的“陣列”再使用 這個方法的 話 就會掉進萬丈深坑 !我們來看圖
因為 不是 標準定義的陣列 我們沒法像上面這樣直觀的 表現出來 我們取 區域性的圖 來說明問題的所在。
因為只要開闢成功 那麼 我讀 P[0][0] 是不是應該是一個隨機值。 對,我就要它讀出隨機值的圖來分析 。
這個 就是執行memset之前的 P[0][0] 的情況 我們看到了 隨機值。
然後我萬惡的點選了單步。
結果就是這樣的
WTF 讀不出來了 但是 P[1][0]卻能讀出來 而且 並沒有初始化 如圖:
沒有初始化我就不怪你了 還讓我讀不出來 ~~~ 什麼破編譯器 炸了算了。
但是我沒有炸 我 把 P[0]和 NULL 做了一個比較
注意看我單步的黃色游標 我單步了哦 別看走眼
NULL NULL 我發現了什麼 我發現了是 NULL 耶!從此學了一個新詞 NULL 來 NULL 去 歡迎廣大讀友用來造句。哈哈
這樣所有的謎題就解開了? 沒有,因為 P[1]!=NULL 那這個又是怎麼回事呢?
我們把目光投向那個 sizeof(P) 這裡 按照我們正常的思維 我們猜一下 這個運算的結果是什麼?答案是 4 !!
誒 我不是開了100的那個二維指標空間了嗎?咋就是 4 了????而且這100個空間都是連續的啊!!
有些稀裡糊塗的人馬上就站出來 理直氣壯的說 這個就是 4 沒錯啊,就同一般定義的二維陣列一樣啊 。不一樣 我們看
是不是 4萬 ??????? 說明了一般的陣列是可以計算出陣列 "連續" 空間的大小的 因為整數型 int 一個空間的大小是 4 ,100行100列一共有 100*100 == 10000個元素 所以 10000*4 == 40000 。
四...四萬是麼?剛剛看錯了,對啊 就是 4萬啊 。(你給我粗去~~馬上立刻~ )
那麼為什麼 是 4 呢? 有的人又說了 那有可能是 sizeof(a[0]) ; 不對了啊~ 這個是 400 就不附圖了 截圖浪費時間啊
那麼 4 從哪來 它又要到哪裡去呢?????????? 總不能讓他 NULL來NULL去吧!
然後我就試了一下這一組:
我們想一下 剛剛的P是不是一個二維的指標 那麼這個4 是不是就是那個4了?
我回去看了一下 P的定義
啊~~~我尖叫了出來,手裡的辣條 都忘記了 。
這這這這 ,這不是 變 變數嗎 我不敢相信我的眼睛 於是我做了一個測試。
這下問題就徹底的暴露出來了
正經的解釋開始:
1.P 無論怎樣給它開空間 說到頭 它就是一個變數 一個二維指標的變數,所以 用它計算空間的值自然就是 sizeof(空間的型別);
也就等同於sizeof(int**) 這個實驗我們上面已經做過了 答案是 4
2.所以 我們 完全的瞭解了。
那麼我們怎麼解決初始化的問題呢 不會有是兩個for吧 不是的啦 怎麼這麼 “土”呢?
我們還記得 calloc嗎 用它來開闢的二維陣列的空間預設就是初始化為 0 了唄 。
我們看下圖
解決初始化問題。而且 嘿嘿~~
沒有執行 if 它不再是一個NULL來NULL去的指標了~~
解決問題了。
忘記幾個人真的好難啊!我好想回到大學以前 可是 又不能多想 因為現在自己的命運捏在自己手上,即使受傷也要 前進。