2017-03-06 36 views
-1

我試圖重構我的代碼,使之更好/更可讀所以我想更改2- d變量數組分配如下C中傳遞可變大小2-d陣列起作用

// OLD CODE 
int **map; 
     map = calloc(number, sizeof(int *)); 
     if (!(map)) { 
      free(map); 
      return 1; 
     } 
     for (int i = 0; i < number; i++) { 
      map[i] = calloc(number, sizeof(int)); 
      if (!(map[i])) { 
       while (--i >= 0) { 
        free(map[i]); 
       } 
       free(map); 
       return 1; 
      } 
     } 

// NEW CODE 
int (*map)[number] = malloc(sizeof (int[number][number])); 
if (!(map)){ 
    free(map); 
    return 1; 
} 

問題是我所有使用地圖的函數都需要int **map,並且通過更改地圖的聲明來像我一樣,IDE告訴我incorrect type int[]* instead of int** 我應該使用什麼而不是int**?在函數聲明中使用int[]* map告訴我can't resolve variable map

+1

'型FUNC(INT N,INT(*地圖)[N]);'調用'FUNC(號,地圖);' – BLUEPIXY

+0

幫自己一個忙,只是創建一個平面數組,然後通過數組[y * width + x] = value來引用行; –

+0

@MalcolmMcLean我在想這個,有沒有辦法分配一半的地圖大小,而不必擔心索引的順序?在我的地圖位置[i] [j]和[j] [i]將始終具有相同的值,但現在我分配兩倍所需的大小以便不必擔心i和j的順序。 –

回答

0

原來,下面的代碼不是C99替代@M.M,而是GCC擴展。

Undocumented GCC Extension: VLA in struct


作爲 C99 GCC擴展替代int (*map)[number] = malloc(sizeof (int[number][number]));代碼簡化和保持與現有的功能設定的兼容性,分配所有存儲器需要具有1個*alloc()呼叫。

這確實需要當代碼與map完成時,所有內存都被釋放,其中一個爲free(map)。此外,map[]的單個行不能再被重新分配,但可以在map[]內交換。

int **map_allocate(size_t row, size_t column) { 
    struct { 
    int *ip[row];  // Array of pointers, followed by a ... 
    int i[row][column]; // 2D array of int 
    } *u; 
    u = calloc(1, sizeof *u); 
    if (u == NULL) { 
    return NULL; 
    } 
    for (size_t i = 0; i<row; i++) { 
    u->ip[i] = u->i[row]; 
    } 
    return &u->ip[0]; 
} 

注意:沒有鑄造和字段i[][]正確對齊。

+0

結構不能包含VLAs –

+0

@ M.M有趣。然而這裏的'u'不是'struct',而是一個指針 - 但我希望這不會產生足夠的差異。一位編譯人員接受了它(很好地啓用了 - 或者我認爲 - 因此也是這篇文章),另一位編者警告​​說,「一個結構或聯合的成員不能有一個可變的修改類型」。我將審查。 – chux

+0

@ M.M好吧,它看起來像我回到了繪圖板。太糟糕了,它確實看起來像一個漂亮的解決方案。 – chux

0

要使用與標準的代碼,unlike the other answer一個分配,是作爲一個需要確保指針和int需求的組合的存儲器分配,以滿足對準關切的int對準要求的不尋常的情況下超過指針對準那些有點麻煩。這可以更容易地用long long顯示如下。

如果這讓「代碼更容易閱讀」留給OP的判斷。

#include <stdlib.h> 
#include <stdio.h> 

long long **map_allocate_ll(size_t row, size_t column) { 
    long long **map; 
    long long *ints; 

    size_t pointers_sz = sizeof *map * row; 
    // extend pointer size to `*ints` boundary 
    pointers_sz = (pointers_sz + sizeof *ints - 1)/sizeof *ints * sizeof *ints; 
    size_t ints_sz = sizeof *ints * row * column; 
    printf("psize %zu, isize %zu\n", pointers_sz, ints_sz); 

    map = calloc(1, pointers_sz + ints_sz); 
    if (map == NULL) { 
    return NULL; 
    } 
    ints = (void*) ((char*) map + pointers_sz); 
    printf("map %p\n", (void *) map); 
    for (size_t i = 0; i<row; i++) { 
    map[i] = &ints[i * column]; 
    printf("map[%zu] %p\n", i, (void *) map[i]); 
    } 
    return map; 
} 

int main() { 
    free(map_allocate_ll(5,3)); 
} 

樣本輸出

psize 24, isize 120 
map 0x80081868 
map[0] 0x80081880 
map[1] 0x80081898 
map[2] 0x800818b0 
map[3] 0x800818c8 
map[4] 0x800818e0