2

2D 配列を宣言すると

int A[sz][sz];

このオブジェクトへのポインタを作成するにはどうすればよいですか?

関数からポインターへのポインターを介して配列を返したいのですint**が、事前にサイズを知らずに配列を構築したいのでお願いします。サイズは引数として渡されます。動的割り当てを使用せずにこれを行う方法があるかどうか知りたいです。

int** A問題は、関数内で次のようなことをすると、必要なAサイズに関する情報が得られないことです。

2D配列の場合、配列を作成してからこの配列にポインターを割り当てるにはどうすればよいですか。

私はもっ​​と明確にする必要があります。ポインターへのポインターを返したいので、2D配列へのポインターではなく、のようなものになりint**ます。

4

3 に答える 3

2

あなたの問題は、フォーム内の 2D 配列が2 段階の逆参照int**のために の配列を必要とすることです。int*int A[sz][sz];

次のように自分でビルドできます。

int* pointers[sz];
for(size_t i = sz; i--; ) pointers[i] = A[i];

A[i]これはばかげているように思えるかもしれませんが、Cint ()[sz]が配列を処理する方法に根ざしていますi。しかし、代入でその配列を使用すると、そのサブ配列の最初の要素へのポインターに減衰int*します。これは型です。ループの後、Apointersは 2 つの非常に異なるものです ( のタイプAint ()[sz][sz])

サイドノート:関数からこれを返したいと言います。配列がスタックに割り当てられている場合、その data へのポインターを返してはなりません。関数が戻るとすぐに消えます。staticストレージを持っているか、別の既存のオブジェクトの一部であるオブジェクトへのポインター/参照のみを返すことができます。これを守らないと、スタックが破損する可能性があります。

編集:

C に関するあまり知られていない事実は、配列が減衰するポインター型だけでなく、実際の C 配列へのポインターを実際に渡すことができるということです。これを示す小さなプログラムを次に示します。

#include <stddef.h>
#include <stdio.h>

int (*foo(int size, int (*bar)[size][size], int y))[] {
    return &(*bar)[y];
}

int main() {
    int mySize = 30;
    int baz[mySize][mySize];
    int (*result)[mySize];
    result = foo(mySize, &baz, 15);
    printf("%ld\n", (size_t)result - (size_t)baz);
}

このサンプル プログラムの期待される出力は 1800 です。重要なことは、配列の実際のサイズを、コンパイル時の定数にするか、配列ポインターと一緒に渡すことによって知る必要があるということです。配列ポインターの場合、サイズ引数は配列ポインターより前に指定する必要があります)。

于 2013-09-17T22:00:08.557 に答える
1

あなたの質問を少し具体化させてください。あなたは言及します:

関数から配列[...]を返したいのですが、事前にサイズを知らずに配列を構築したいのでお願いします。サイズは引数として渡されます。動的割り当てを使用せずにこれを行う方法があるかどうか知りたいです。

I want to return an array from a function [...] size passed as an argument の場合、どこでも使用でき、基になる配列へのアクセスが必要なときにstd::vectorそのメソッドを呼び出すことが合理的だと思われます(これは、.data()連続してください)。例えば:

std:vector<double> myfun(size_t N) {
 std::vector<double> r(N);
 // fill r[0], r[1], ..., r[N-1]
 return r;
}

// later on:
r.data(); // gives you a pointer to the underlying double[N]

I want to do this without dynamic allocationについては、コンパイル時にサイズがわからない限り、それは不可能です。その場合は、以前とまったく同じように行いますがstd::array、既知のコンパイル時のサイズに基づいて最適化を実装できる を使用します。

std::array<double, N> myfun() {
 std::array<double, N> r;
 // fill r[0], r[1], ..., r[N-1]
 return r;
}

// later on:
r.data(); // gives you a pointer to the underlying double[N]

一般的に言えば、実際には、任意のコンテナーを操作できるテンプレート関数を使用します。

template<typename T>
void myfun(T& data) {
  for(int k=0; k<data.size(); k++) {
    // do stuff to data[k]
 }
}

// call as, for example:
std::vector<double> data(10);
myfun(data);

// or equally valid:
std::array<double, 10> data;
myfun(data);

最後に、2 次元データを扱っている場合は、Matrix を行優先の順序で保存するときは次のことを覚えておいてください。

Matrix [1, 2; 3 4] is stored as [1 2 3 4]

(i, j)その後、 を呼び出して行列の要素を参照できますdata[i * ncols + j]。例: 3 行 4 列の行列を考えてみましょう。

a b c d
e f g h
i j k l

要素(2, 2)(つまり、ゼロベースの C 型インデックスを想定しているため、3 行目、3 列目) は次のように計算されますM[2][2] = M[2 * 4 + 2] = M[10] = k。これは、次のように保存されているためです。

 [a b c d e f g h i j  k  l]
 [0 1 2 3 4 5 6 7 8 9 10 11]

andkは index を持つ要素10です。

于 2013-09-17T22:00:54.883 に答える