0

質問は信じられないほど単純に見えるかもしれませんが、double 配列を返す関数を c で宣言するにはどうすればよいでしょうか。例えば

char myfunction(int a, int b)
{
...
char d[a][b];
...
return d;
}

しかし、それは機能していないようです (応答が「malloc」と「free」の使用法を回避できる場合、それらの種類の基本的な使用法を理解することがより役立つ可能性があります)。

ベスト、ニューベン

4

4 に答える 4

3

しかし、それは機能していないようです (応答が「malloc」と「free」の使用法を回避できる場合、それらの種類の基本的な使用法を理解することがより役立つ可能性があります)。

関数が返されると無効なポインターを返すことを提案しているため、できません。配列は自動ストレージ期間で宣言されているため、関数が戻ると、その配列へのすべての参照は無効になります。C の関数から配列を返すことはできません。

関数にデータを入力する必要がある場合は、関数内から取得したchar**を返しmallocます。

char **foo(int cols, int rows) {
  char **ret = malloc(rows * sizeof(char*));
  if(!ret)
    return ret;

  for(int i = 0; i < rows; ++i) {
    ret[i] = malloc(cols);
    /* error checking again for malloc,
       call free() on pointers 0...i upon failure.
       memset to 0 if you like */
  }

  return ret;
}

戻り値で多次元配列構文を使用できるようになりました。

char **p = foo(10, 20);

// p[j] returns a pointer to char, p[j][k] returns a char
char elem = p[j][k];
于 2012-07-23T20:04:07.563 に答える
1

C99以降のCでは、他の回答のようにエミュレーションではなく、実際の2D配列を割り当てる正しい方法は、次のようなことです:

char (*array)[cols] = malloc(cols * rows);

関数でそれをしなければならない場合、私にとって最も簡単な方法は

void * foo(int cols, int rows) {
  char (*ret)[cols] = malloc(rows * cols);
  // do something with it
  return ret;
}

それを呼び出すときは、新しい変数に次元を与えるためにもう少し注意する必要があります

char (*array)[cols] = foo(cols, rows);

これらすべてには、連続するオブジェクトを割り当てるために 1 つの単純な関数が使用され、メモリの割り当てを解除するために最後に をmalloc1 回呼び出すだけでよいという利点があります。free

于 2012-07-23T21:31:48.083 に答える
1

このような状況では、malloc と free を避けることはできません。問題は宣言することです

char d[a][b];

配列をスタックに直接割り当てているため、関数が返されると配列の割り当てが解除され、返されたアドレスは無効になります。

次のようなものを使用します。

char** myfunction(int a, int b) {
    char** d = (char**)malloc(a * sizeof(char*));

    if (d ! = NULL) {
        for (int i = 0; i < b; i++) {
            d[i] = (char*)malloc(sizeof(char));

            if (d[i] == NULL) {
                for (int j = 0; j < i; j++) {
                    free(d[j]);
                }

                free(d);
                d = NULL;

                break;
            }
        }
    }

    return d;
}
于 2012-07-23T20:06:44.147 に答える
1

C では、関数で配列を作成して呼び出し元に返す場合は、動的にメモリを割り当てる別の関数 (または など) またはを使用する必要があります。その後、配列へのポインターを返すことができます。malloccallocrealloc

char **make2dArray(int x, int y) {
    int i;
    char **array = calloc(x, sizeof(char*));
    for(i = 0; i < x; i++) {
        array[i] = calloc(y, sizeof(char));
    }
    return array;
}

一方、単に配列の値を変更する必要がある場合は、配列をパラメーターとして取得し、その場で変更することをお勧めします。

void modify2dArray(int x, int y, char **array) {
    int i, j;
    for(i = 0; i < x; i++) {
        for(j = 0; j < y; j++) {
            array[i][j] = 1;
        }
    }
}

そして、動的に割り当てられたメモリを使い終わったら、割り当てごとに free を呼び出すことを忘れないでください。

void dealloc2dArray(int x, int y, char **array) {
    int i;
    for(i = 0; i < x; i++) {
        free(array[i]);
    }
    free(array);
}

これらの関数を使用すると、次のようになります。

char **array = NULL;
array = make2dArray(5,6);
modify2dArray(5,6,array);
dealloc2dArray(5,6);
array = NULL;

malloc動的割り当て関数 ( 、calloc、およびrealloc) は失敗して NULL を返す可能性があることに注意してください。スペースを節約するために、ここでは割り当てごとに NULL をチェックしませんでしたが、通常は、割り当てが成功することを確認することをお勧めします。

于 2012-07-23T20:15:44.660 に答える