ホームページ > バックエンド開発 > C++ > 境界を超えたポインタ演算を使用して 2D 配列要素にアクセスすると、未定義の動作が発生しますか?

境界を超えたポインタ演算を使用して 2D 配列要素にアクセスすると、未定義の動作が発生しますか?

Mary-Kate Olsen
リリース: 2024-12-31 12:35:09
オリジナル
507 人が閲覧しました

Does Accessing a 2D Array Element Using Pointer Arithmetic Beyond Its Bounds Result in Undefined Behavior?

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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート