2D 配列は連結された 1D 配列として扱うことができますか?
次のコード スニペットを考えてみましょう:
int a[25][80]; a[0][1234] = 56; int* p = &a[0][0]; p[1234] = 56;
質問: コードは配列を超えてアクセスしますか?その境界により、未定義の動作が発生しますか?
答え: はい、2 行目と 4 行目はどちらも未定義の動作を示します。
C では、配列のインデックス付けは基本的にポインタ演算です。 a[i][j] にアクセスすると、コンパイラはそれを *(a[i] j) に効果的に変換します。同様に、p[i] は *(pi) を参照します。
この場合、配列 a の次元は 25 x 80 です。配列の最初の行 a[0] には 80 個の要素が含まれます (範囲は 80 x 80)。 a[0][0] から a[0][79]) に割り当てられ、連続したメモリ位置に割り当てられます。
にアクセスすることでa[0][1234] の場合、a[0] には範囲 [0, 79] 内の要素のみが含まれているにもかかわらず、コードは最初の行のインデックス 1234 にある要素にアクセスしようとします。これは範囲外であり、未定義の動作を引き起こします。
同じロジックが 4 行目に適用されます。p は a[0] の最初の要素を指しますが、配列の次元は依然として 25 x 80 です。 p[ へのアクセス1234] は本質的に範囲外のポインター算術演算であり、再び未定義の動作を引き起こします。
さらに、 Language Lawyer は、コメントで、constexpr を使用した同様のコード スニペットは、コンパイラが定数式でそのような未定義の動作を検出するためにコンパイルに失敗すると指摘しました:
constexpr int f(const int (&a)[2][3]) { auto p = &a[0][0]; return p[3]; } int main() { constexpr int a[2][3] = { 1, 2, 3, 4, 5, 6, }; constexpr int i = f(a); }
これは、p[3] にアクセスしているため、正しくコンパイルされます。 constexpr を使用すると、コンパイラが未定義の動作を検出し、エラーをスローします。
以上が境界を超えたポインタ演算を使用して 2D 配列要素にアクセスすると、未定義の動作が発生しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。