私は、良い(そして実用的な)解決策を与えるものについていくつかの質問があることを知っていますが、これを達成するための最良の方法は何かを明確に言うIMHOはありません。したがって、2D配列があるとします。
int tab1[100][280];
この2D配列を指すポインターを作成します。これを実現するために、次のことができます。
int (*pointer)[280]; // pointer creation
pointer = tab1; //assignation
pointer[5][12] = 517; // use
int myint = pointer[5][12]; // use
または、代わりに:
int (*pointer)[100][280]; // pointer creation
pointer = &tab1; //assignation
(*pointer)[5][12] = 517; // use
int myint = (*pointer)[5][12]; // use
両方ともうまくいくようです。今、私は知りたい:
//defines an array of 280 pointers (1120 or 2240 bytes)
int *pointer1 [280];
//defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
int (*pointer2)[280]; //pointer to an array of 280 integers
int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers
pointer2
またはpointer3
を使用すると、 WhozCraig で指摘されている++pointer2
と同じ操作を除き、同じバイナリが生成されます。
typedef
を使用することをお勧めします(上記と同じバイナリコードを生成するpointer3
)
typedef int myType[100][280];
myType *pointer3;
注:C++ 11以降では、using
の代わりにキーワードtypedef
も使用できます。
using myType = int[100][280];
myType *pointer3;
あなたの例では:
myType *pointer; // pointer creation
pointer = &tab1; // assignation
(*pointer)[5][12] = 517; // set (write)
int myint = (*pointer)[5][12]; // get (read)
注:配列tab1
が関数本体内で使用される場合、この配列は呼び出しスタックメモリ内に配置されます。ただし、スタックサイズには制限があります。空きメモリスタックよりも大きな配列を使用すると、 stack overflowcrash が生成されます。
完全なスニペットは gcc.godbolt.org でオンラインコンパイル可能です
int main()
{
//defines an array of 280 pointers (1120 or 2240 bytes)
int *pointer1 [280];
static_assert( sizeof(pointer1) == 2240, "" );
//defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
int (*pointer2)[280]; //pointer to an array of 280 integers
int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers
static_assert( sizeof(pointer2) == 8, "" );
static_assert( sizeof(pointer3) == 8, "" );
// Use 'typedef' (or 'using' if you use a modern C++ compiler)
typedef int myType[100][280];
//using myType = int[100][280];
int tab1[100][280];
myType *pointer; // pointer creation
pointer = &tab1; // assignation
(*pointer)[5][12] = 517; // set (write)
int myint = (*pointer)[5][12]; // get (read)
return myint;
}
_int *pointer[280];
_ // int型の280個のポインターを作成します。
32ビットOSでは、各ポインターに4バイト。 4 * 280 = 1120バイトです。
int (*pointer)[100][280];
// [100] [280] intの配列を指すために使用されるポインターを1つだけ作成します。
ここでは4バイトのみです。
質問に来ると、int (*pointer)[280];
とint (*pointer)[100][280];
は異なりますが、[100] [280]の同じ2D配列を指します。
int (*pointer)[280];
がインクリメントされると、次の1D配列を指しますが、int (*pointer)[100][280];
は2D配列全体を横切り、次のバイトを指します。そのバイトにアクセスすると、そのメモリがプロセスに属していない場合に問題が発生する可能性があります。
どちらの例も同等です。ただし、1つ目はそれほど明白ではなく、より「ハッキング」ですが、2つ目は明確にあなたの意図を述べています。
int (*pointer)[280];
pointer = tab1;
pointer
は、280個の整数の1D配列を指します。割り当てでは、実際に最初のrow of tab1
を割り当てます。これは、暗黙的に配列をポインター(最初の要素)にキャストできるため機能します。
pointer[5][12]
を使用している場合、Cはpointer
を配列の配列として処理します(pointer[5]
はint[280]
型です)、別の暗黙があります=ここにキャストします(少なくとも意味的に)。
2番目の例では、2D配列へのポインターを明示的に作成します。
int (*pointer)[100][280];
pointer = &tab1;
セマンティクスはここでより明確です:*pointer
は2D配列なので、(*pointer)[i][j]
を使用してアクセスする必要があります。
どちらのソリューションも同じ量のメモリ(1ポインター)を使用するため、ほとんどの場合同じ速度で実行されます。内部では、両方のポインターが同じメモリー位置(tab1
配列の最初の要素)を指しており、コンパイラーが同じコードを生成することもあります。
最初の解決策は「より高度」です。何が起こっているのかを理解するには、Cで配列とポインターがどのように機能するかを深く理解する必要があるためです。 2つ目はより明示的です。