2017-03-06 31 views
-1

が、私はそれが/より良いので、私はC可変サイズ2次元配列が

// 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; 
} 

を次のように2-D変数配列の割り当てを変更しようとして読みやすくするために私のコードをリファクタリングしようとしている関数に渡します問題は、マップを使用するすべての関数が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の順序について心配する必要がないように、必要なサイズを2倍に割り当てます。 –

答えて

0

が表示されます。以下のコードはC99の代替品ではありませんが、@M.MではなくGCC拡張です。

Undocumented GCC Extension: VLA in struct


コードの簡略化のためint (*map)[number] = malloc(sizeof (int[number][number]));から C99 GCC拡張代替として及び1つの*alloc()呼に必要なすべてのメモリを割り当て、既存の機能セットとの互換性を維持します。

これは、mapでコードが実行されるとき、すべてのメモリが1つの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

ストラクチャーにはVLAが含まれていない –

+0

@ M.M興味深い。しかし、ここでの 'u'は' struct'ではなく、一つのポインタですが、十分な違いがないと期待しています。あるコンパイラがそれを受け入れました(そう思っていたので、私は思っていましたので、この記事を読んでいます)。そしてもう一つは、あなたが言うように、 "構造体または共用体のメンバーは可変的に変更された型を持つことができません"私は見直すだろう。 – chux

+0

@ M.Mまあ、私はドローイングボードに戻っているようです。あまりにも悪い、それは素晴らしい解決策のように見えた。 – chux

0

標準コード、unlike the other answer有するもの割り当てを使用する1つの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