[問題] 2D 陣列之記憶體位址有移位情形

看板C_and_CPP (C/C++)作者 (gowrite)時間3年前 (2021/05/02 07:10), 編輯推噓7(7012)
留言19則, 9人參與, 3年前最新討論串1/1
開發平台(Platform): (Ex: Win10, Linux, ...) GNU/Linux 編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出) GCC 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...) N/A 問題(Question): 印象中, 陣列不管是幾維的,記憶體位址應該是連續分佈, 但實際上有規則性跳躍的情況 想問各位,這樣的行為有專有名詞嗎? 謝謝 餵入的資料(Input): 請看下方程式碼 預期的正確結果(Expected Output): 預期 二維陣列 在 row 0 到 row 1 時, 記憶體的位址也是連續, 但實際上展現出來是會跳躍 找 0 尾數為 下一個 row 的開頭 錯誤結果(Wrong Output): 無錯誤,想知道是編譯器的問題,還是 C 語言的正常規格行為 程式碼(Code):(請善用置底文網頁, 記得排版,禁止使用圖檔) int row = 2; int col = 3; // 建立 二維 int 陣列 int **arr = malloc(sizeof(int *) * row); for(int i=0 ; i<row ; i++){ arr[i] = malloc(sizeof(int) * col); } // 填入數值 for(int i=0 ; i<row ; i++){ for(int j=0 ; j<col ; j++){ arr[i][j] = i+ ((j+1)*2); } } 當 row = 2, col = 3 時 row :0, col :0, arr[0][0] = 2, 0x55963ccf92c0 row :0, col :1, arr[0][1] = 4, 0x55963ccf92c4 row :0, col :2, arr[0][2] = 6, 0x55963ccf92c8 row :1, col :0, arr[1][0] = 3, 0x55963ccf92e0 row :1, col :1, arr[1][1] = 5, 0x55963ccf92e4 row :1, col :2, arr[1][2] = 7, 0x55963ccf92e8 可以看到 row 1 跟 row 2 中間從 92c8 跳到了 92e0 多跳了 4 bytes 當 row = 2, col = 4 時 row :0, col :0, arr[0][0] = 2, 0x55b7ab0542c0 row :0, col :1, arr[0][1] = 4, 0x55b7ab0542c4 row :0, col :2, arr[0][2] = 6, 0x55b7ab0542c8 row :0, col :3, arr[0][3] = 8, 0x55b7ab0542cc row :1, col :0, arr[1][0] = 3, 0x55b7ab0542e0 row :1, col :1, arr[1][1] = 5, 0x55b7ab0542e4 row :1, col :2, arr[1][2] = 7, 0x55b7ab0542e8 row :1, col :3, arr[1][3] = 9, 0x55b7ab0542ec 這樣就正常 當 row = 2, col = 5 時 row :0, col :0, arr[0][0] = 2, 0x55eea8bac2c0 row :0, col :1, arr[0][1] = 4, 0x55eea8bac2c4 row :0, col :2, arr[0][2] = 6, 0x55eea8bac2c8 row :0, col :3, arr[0][3] = 8, 0x55eea8bac2cc row :0, col :4, arr[0][4] = 10, 0x55eea8bac2d0 row :1, col :0, arr[1][0] = 3, 0x55eea8bac2e0 row :1, col :1, arr[1][1] = 5, 0x55eea8bac2e4 row :1, col :2, arr[1][2] = 7, 0x55eea8bac2e8 row :1, col :3, arr[1][3] = 9, 0x55eea8bac2ec row :1, col :4, arr[1][4] = 11, 0x55eea8bac2f0 居然從 c2d0 多跳了 12 個 bytes 硬是跳到 c2e0 開頭 補充說明(Supplement): N/A -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.171.199.9 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1619910624.A.69C.html

05/02 07:44, 3年前 , 1F
因為你並不是為底層結構配置連續記憶體 (你的 for/malloc)
05/02 07:44, 1F

05/02 07:45, 3年前 , 2F
也就是說, 對系統來說你的每一列都是個別一塊記憶體
05/02 07:45, 2F

05/02 07:45, 3年前 , 3F
因此它們之間就並不一定有什麼位置上的關係了
05/02 07:45, 3F

05/02 07:46, 3年前 , 4F
會在附近只是因為剛好那附近都還沒人用而已
05/02 07:46, 4F

05/02 07:47, 3年前 , 5F
要配置成連續的也不是不行, 但就不是 for/malloc 一列一列
05/02 07:47, 5F

05/02 07:47, 3年前 , 6F
要, 而是一口氣要來一整塊之後指定每一列進列指標陣列
05/02 07:47, 6F

05/02 07:51, 3年前 , 7F
另外, cc 到 e0 沒有連續喔, 中間還有 d
05/02 07:51, 7F

05/02 08:29, 3年前 , 8F
你是配置了複數個一維陣列而不是一個二維...
05/02 08:29, 8F

05/02 09:25, 3年前 , 9F
malloc二維陣列應該是for loop malloc多個一維陣列
05/02 09:25, 9F

05/02 09:28, 3年前 , 10F
編譯器沒問題,C語言也沒問題,單純只是寫法bug
05/02 09:28, 10F

05/02 09:30, 3年前 , 11F
寫code懷疑編譯器有問題的,我是頭一個看到.........
05/02 09:30, 11F

05/02 12:11, 3年前 , 12F
code寫錯,懷疑編譯器/程式語言/電腦有錯的人,很多啊
05/02 12:11, 12F

05/02 17:48, 3年前 , 13F
正確寫法應該是先malloc一個大小為row*col的連續記
05/02 17:48, 13F

05/02 17:48, 3年前 , 14F
憶體,在一一把pointer指向每個row的開頭 這樣就會
05/02 17:48, 14F

05/02 17:48, 3年前 , 15F
是連續的了
05/02 17:48, 15F

05/02 21:19, 3年前 , 16F
很有想法 !
05/02 21:19, 16F

05/03 10:29, 3年前 , 17F
一樓專業
05/03 10:29, 17F

05/03 11:17, 3年前 , 18F
你呼叫了好多次malloc() 這樣當然沒有保證連續
05/03 11:17, 18F

05/04 18:26, 3年前 , 19F
就算是一次分配 陣列只有1D/2D "剛好"連續
05/04 18:26, 19F
文章代碼(AID): #1WZT_WQS (C_and_CPP)
文章代碼(AID): #1WZT_WQS (C_and_CPP)