2次元配列へのポインタを作成する 質問する

2次元配列へのポインタを作成する 質問する

静的な 2 次元配列へのポインタが必要です。これはどのように実現しますか?

static uint8_t l_matrix[10][20];

void test(){
   uint8_t **matrix_ptr = l_matrix; //wrong idea 
}

次のようなさまざまなエラーが発生します:

  • 警告: 互換性のないポインタ型からの代入
  • 添字の値は配列でもポインタでもない
  • エラー: フレキシブル配列メンバーの使用が無効です

ベストアンサー1

ここでは配列の最初の要素へのポインタを作成します

uint8_t (*matrix_ptr)[20] = l_matrix;

typedefを使うと、見た目がきれいになります

typedef uint8_t array_of_20_uint8_t[20];
array_of_20_uint8_t *matrix_ptr = l_matrix;

そうすれば、また人生を楽しむことができます:)

matrix_ptr[0][1] = ...;

注意してくださいポインタ/配列の世界C では、この点に関して多くの混乱が生じます。


編集

コメント欄が短すぎてできないので、他の回答をいくつかここで確認します。複数の代替案が提案されましたが、どのように動作するかは示されていません。これがその方法です。

uint8_t (*matrix_ptr)[][20] = l_matrix;

&エラーを修正し、次のスニペットのようにアドレス演算子を追加すると、

uint8_t (*matrix_ptr)[][20] = &l_matrix;

次に、20個のuint8_t配列型の要素の不完全な配列型へのポインタを作成します。ポインタは配列の配列へのポインタなので、次のようにアクセスする必要があります。

(*matrix_ptr)[0][1] = ...;

そして、それは不完全な配列へのポインタなので、できないショートカットとして行う

matrix_ptr[0][0][1] = ...;

インデックス付けには要素型のサイズがわかっている必要があるためです(インデックス付けはポインタに整数を追加することを意味するため、不完全な型では機能しません)。これは と が互換性のある型であるCため、でのみ機能することに注意してください。C++ には の概念がありません。T[]T[N]互換性のあるタイプであり、 と はT[]異なるT[10]型であるため、そのコードは拒否されます。


次の代替案はまったく機能しません。配列の要素の型は、1次元配列として見ると、ない uint8_t、 しかしuint8_t[20]

uint8_t *matrix_ptr = l_matrix; // fail

以下は良い代替案です

uint8_t (*matrix_ptr)[10][20] = &l_matrix;

アクセスするには

(*matrix_ptr)[0][1] = ...;
matrix_ptr[0][0][1] = ...; // also possible now

外側の寸法が保持されるという利点があります。そのため、sizeofを適用することができます。

sizeof (*matrix_ptr) == sizeof(uint8_t) * 10 * 20

配列内の項目が連続して格納されるという事実を利用したもう1つの答えがあります。

uint8_t *matrix_ptr = l_matrix[0];

さて、これでは形式的には2次元配列の最初の要素の要素にのみアクセスできます。つまり、次の条件が満たされます。

matrix_ptr[0] = ...; // valid
matrix_ptr[19] = ...; // valid

matrix_ptr[20] = ...; // undefined behavior
matrix_ptr[10*20-1] = ...; // undefined behavior

おそらく まで動作するでしょう10*20-1が、エイリアス分析やその他の積極的な最適化を行うと、一部のコンパイラは、そのコードが壊れる可能性があると想定する可能性があります。そうは言っても、その点で失敗するコンパイラに出会ったことはありません (ただし、実際のコードでその手法を使用したことはありません)。C FAQ にもその手法が含まれています (UB に関する警告付き)。配列型を変更できない場合は、これが最後の手段です :)

おすすめ記事