2

まず第一に、私は C プログラミングの専門家ではなく、現在、いくつかのレガシー C コードを読んでいます。そこで、2D マトリックスを初期化するための次の関数を見つけました。

long int **computeDistanceMatrix(void){
    long int i;
    long int j;
    long int ** matrix;
    matrix = malloc(sizeof(long int) * numberOfCities * numberOfCities +
        sizeof(long int *) * numberOfCities);

    if(matrix == NULL){
        fprintf(stderr, "Out of memory, exit.");
        exit(1);
    }

    for (i = 0; i < numberOfCities; i++){
        matrix[i] = (long int*) (matrix + numberOfCities) + i * numberOfCities;
        for (j = 0; j < numberOfCities; j++){
            matrix[i][j] = distanceFunction(i, j);
        }
    }
    return matrix;
}

これに似た、より明確に見えるものを期待していたので、コードが少し奇妙であることがわかりました。とにかく、次のことが気になりました。

  • malloc(sizeof(long int) * numberOfCities * numberOfCities + sizeof(long int *) * numberOfCities)は、データ項目と各行へのポインターにメモリを割り当てていることを意味しますか?
  • とはどういう意味matrix[i] = (long int*) (matrix + numberOfCities) + i * numberOfCitiesですか? 彼らがやろうとしていることは本当に理解できません。
  • Cで2D配列のメモリ割り当てを行うより簡単な方法はありますか、それとも適切な方法ですか?
4

6 に答える 6

2

sizeof (long int) = ln都市、およびが与えられた場合、このコードは、質問でリンクしている記事sizeof (long int *) = pとほぼ同じことを試みます。ただ、多くの呼び出しではなく、1 回の呼び出しでそれを実行しようとします。malloc

np割り当てられた最初のバイトは、nポインターを保持するために使用されます。nlこれらの各ポインターは、長い整数のチャンクを指します。もちろん、long intブロックはすべて隣接しており、最初のブロック自体はnp サイズのポインターのブロックに隣接し、アドレスから始まりますmatrix + np

この線: matrix[i] = (long int*) (matrix + numberOfCities) + i * numberOfCities

.. これらの各nポインターを、ブロック内の正しい場所を指すように設定します。うまくいけば、次の ASCII アートがそれを十分に明確にします ;)

(addr = matrix +)  0    p    2p .. np   np+nl np+2nl

[matrix]-------->[ v    v    v  .. ^    ^     ^
                   |    |    |     |    |     |
                   |____|____|_____|    |     |
                        |____|__________|     |
                             |________________|

この種の「最適化」(読みやすさを犠牲にして)が利点をもたらすかどうかはわかりません。いくつかは次のとおりです。

  1. mallocおそらく、実装で行う必要のある簿記の量が減ります。ただし、ポインター値を自分で計算するようになったため、追加のコストも発生します。

  2. 2D 配列全体を 1 回の呼び出しで取り除くことができますfree(もちろん、コードを解放するプログラマーは、1 回のfree呼び出しですべてを行う必要があることを認識しておく必要があるという問題があります)。

  3. キャッシュに関して利点があるかもしれません。配列は 1 つのブロック内にあり、空間的な局所性が作用します。一方、複数のmalloc呼び出しは、互いに遠く離れたブロックを返す可能性があります。

于 2013-11-03T23:11:50.423 に答える
1

2D 配列を作成する簡単な方法は次のとおりです。

long** create2DArray(int rows, int cols)
{
    // create an array of long* pointers
    long** ptr = (long**) malloc(sizeof(long*) * rows);

    for(int i = 0; i < rows; i++)
    {
        // allocate an array for each row
        ptr[i] = (long*)malloc(sizeof(long) * cols));
    }
    return ptr;
}

int main()
{
    long int** ptr = create2DArray();
    return 0;
}
于 2013-11-03T22:58:28.780 に答える
0

これは、2D 配列を動的に割り当てる別の方法です。

#include <stdlib.h>

int **array;
array = malloc(nrows * sizeof(int *));
if(array == NULL)
    {
    fprintf(stderr, "out of memory\n");
    exit(EXIT_FAILURE); //or return here
    }
for(i = 0; i < nrows; i++)
    {
    array[i] = malloc(ncolumns * sizeof(int));
    if(array[i] == NULL)
        {
        fprintf(stderr, "out of memory\n");
        exit(EXIT_FAILURE); //or return here
        }
    }

主なアイデアは、 int のポインターへのポインターを宣言することです。これが行列 (配列) です。まず、必要な最初の次元に等しいサイズを動的に割り当てます。次に、整数のポインターの別の配列を動的に割り当てます。

あなたが本当に理解しなければならないのは、メモリにスペースを動的に割り当てるときに「次元」がないということです.それらはランダムな場所にすぎません.限界。

于 2013-11-03T22:48:43.417 に答える