C言語関数を2 D配列に戻す方法

1673 ワード

C言語関数を2 D配列に戻すには、次のように定義する人もいます.
int **foo(int rows, int columns)

そして関数の中で苦労してこのようなmalloc文をつづりました.
int (*result)[columns] = (int (*)[columns])malloc(rows * columns * sizeof(int));

関数内でこの配列を読み書きするのは正常で、配列を呼び出し関数に戻した後、この配列を読み書きするとcrashが落ちます.理由は簡単で、関数の戻り値タイプはint**fooであり、実際の戻り値タイプはint(*bar)[columns]であり、foo[1]-foo[0]=sizeof(int*)であり、bar[1]-bar[0]=sizeof(int[columns])である.barをfooに割り当てた後、foo[1][0]にアクセスすると何にアクセスしますか?まずfoo[1]が何なのかを見て、foo[1]=*(foo+1)、その1は1のように見えますが、実際にfooに加算された大きさは実際にはfooが要素の大きさを指しています.sizeof(int)=sizeof(int*)=4と言えば、つまりfoo値を4増やして、このアドレスに値を取り、barに入れて何を取ったのか、実際に取り出したのはbar[0][1]なので、実際foo[1]=bar[0][1]ですがbar[0][1]はポインタや配列ではないのでfoo[1][0]を読むとcrashが落ちます.正しい方法は次のとおりです.
int **result = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++)
{
    result[i] = (int *)malloc(columns * sizeof(int));
}

もちろん、関数のプロトタイプの戻りタイプを変更することもできますが、そうすると関数が難解に見えます.もちろん、構造体を定義して、構造体の中に配列を置くこともできますが、このような欠陥は大きさを固定する必要があり、入力に基づいて動的に指定した大きさの構造体を生成することはできません.前にもブログを書いたことがありますが、参考にしてください.http://blog.csdn.net/imred/article/details/45441457