C言語の基礎知識⑥2次元配列のポインタとアドレス

#include <stdio.h>

int main()
{
    int a[2][3] = {
        2, 4, 6,
        8, 10, 12};
    printf("a:%p, a+1:%p\n", a, a + 1);                 // 相差3*sizeof(int)=12,二维数组名是一个指向每一行的指针,a:0061FF08, a+1:0061FF14
    printf("&a:%p, &a+1:%p\n", &a, &a + 1);             // 相差6*sizeof(int)=1224,&a:0061FF08, &a+1:0061FF20
    printf("a[0]:%p, a[0]+1:%p\n", a[0], a[0] + 1);     // 相差一个sizeof(int)也就是一个数更多v组元素,a[0]:0061FF08, a[0]+1:0061FF0C
    printf("&a[0]:%p, &a:%p\n", &a[0], &a);             // 结果一样,&a[0]:0061FF08, &a:0061FF08
    printf("&a[0]+1:%p, &a+1:%p\n", &a[0] + 1, &a + 1); //&a[0]跳了12个字节(跳过了一行),而&a跳了24个字节(跳过了整个二维数组)

    printf("*a:%p, *a+1:%p,*(a+1):%p\n", *a, *a + 1, *(a + 1)); /* a:0061FF08, *a+1:0061FF0C,*(a+1):0061FF14
                                                                 *a+1偏移了一个sizeof(int).*(a+1)偏移了一行 */
    printf("**a:%p, **a+1:%p,**(a+1):%p\n", **a, **a + 1, **(a + 1));
    printf("*a[0]:%p, *a[0]+1:%p,*(a[0]+1):%p\n", *a[0], *a[0] + 1, *(a[0] + 1));
    printf("*a[1]:%p, *a[1]+1:%p,*(a[1]+1):%p\n", *a[1], *a[1] + 1, *(a[1] + 1));
}
  1. printf("a:%p, a+1:%p\n", a, a + 1);

    出力結果:a:0061FF08, a+1:0061FF14説明:a2次元配列の1行目へのポインタ、a+12次元配列の2行目へのポインタです。各行には 3 つのint要素があるため、差は 3sizeof(int)バイト、つまり 12 バイトになります。

  2. printf("&a:%p, &a+1:%p\n", &a, &a+1);

    出力結果:&a:0061FF08, &a+1:0061FF20説明:&a2次元配列全体のアドレスであり、&a+12次元配列全体の後ろのアドレスです。2 次元配列全体は 2 行 3 列を占め、合計 6 つのint要素があるため、その差は 6sizeof(int)バイト、つまり 24 バイトになります。

  3. printf("a[0]:%p, a[0]+1:%p\n", a[0], a[0]+1);

    出力結果:a[0]:0061FF08, a[0]+1:0061FF0C説明:a[0]2次元配列の1行目であり、最初の要素へのポインタです。各要素は 1 バイトを占めるsizeof(int)ため、違いは 1sizeof(int)バイトです。

  4. printf("&a[0]:%p, &a:%p\n",&a[0], &a);

    出力結果:&a[0]:0061FF08, &a:0061FF08説明:&a[0]2次元配列の1行目のアドレスであり、&a2次元配列の1行目へのポインタと同じです。

  5. printf("&a[0]+1:%p, &a+1:%p\n",&a[0]+1, &a+1);

    出力結果:&a[0]+1:0061FF14, &a+1:0061FF20説明: &a[0]+11 行がスキップされ、これは 2 行目のアドレスを指すことと等価であり、&a+12 次元配列全体がスキップされ、2 次元配列全体の後ろのアドレスを指すことと等価です。

  6. printf("*a:%p, *a+1:%p,*(a+1):%p\n",*a, *a+1,*(a+1));

    出力結果:*a:0061FF08, *a+1:0061FF0C,*(a+1):0061FF14説明:*aこれは最初の行へのポインタです。逆参照後、最初の行の最初の要素が取得されます。これは*a+11 バイトだけオフセットされsizeof(int)、最初の行の 2 番目の要素を指し、*(a+1)2 番目の要素を指します。 row. ポインタは逆参照後、2 行目の最初の要素を取得します。

  7. printf("**a:%p, **a+1:%p,**(a+1):%p\n",**a, **a+1,**(a+1));

    出力結果:**a:00000002, **a+1:00000003,**(a+1):00000008説明: **a1行目へのポインタです。2回逆参照して1行目の最初の要素を取得します。1**a+1行目の最初の要素に1を足します。2**(a+1)行目へのポインタです。 2 回実行すると、2 行目の最初の要素が取得されます。

  8. printf("*a[0]:%p, *a[0]+1:%p,*(a[0]+1):%p\n",*a[0], *a[0]+1,*(a[0]+1));

    出力結果:*a[0]:00000002, *a[0]+1:00000003,*(a[0]+1):00000004説明: *a[0]1 行目の最初の要素であり、参照解除後の要素の値に*a[0]+11 を加え*(a[0]+1)たものです。 1 行目の 2 番目の要素で、参照解除後の要素の値が取得されます。

  9. printf("*a[1]:%p, *a[1]+1:%p,*(a[1]+1):%p\n",*a[1], *a[1]+1,*(a[1]+1));

    出力結果:*a[1]:00000008, *a[1]+1:00000009,*(a[1]+1):0000000A説明:*a[1]2 行目の 1 番目の要素であり、参照解除後の要素の値に*a[1]+11 を加え*(a[1]+1)たものです。 2 行目の 2 行目の要素で、参照解除後の要素の値が取得されます。

ポインターと配列の関連知識ポイントを含めて、いくつかの概要を以下に示します。

  1. ポインタとアドレス: ポインタはメモリのアドレスを格納する変数であり、整数の加減算によってアドレス演算を行うことができます。&演算子は変数のアドレスを取得するために使用されます。

  2. 配列とポインタ: 配列名は、配列の最初の要素へのポインタと考えることができます。2 次元配列の場合、各行は行の最初の要素へのポインタと考えることができます。a[i]または を使用して*(a+i)配列要素にアクセスします。

  3. ポインタ演算: ポインタ演算の結果は、ポインタの型とオペランドの型によって異なります。ポインタを加算または減算する場合、対応するオフセットは、ポインタが指す型のサイズに基づいて実行されます。

  4. 逆参照演算子:*この演算子を使用してポインターを逆参照し、ポインターが指す値を取得します。

  5. printf 形式の出力:%pポインタ アドレスの値を出力するために使用されます。

二次元配列名は行を指し、「&二次元配列名は二次元配列全体を指し「二次元配列名[i]は行 i の最初の要素のアドレスを指します&二次元配列名[i]は行を指します

C 言語では、配列名は配列の最初の要素へのポインタです。つまり、配列名自体が配列の最初の要素のアドレスを表します。a[i]したがって、配列名を使用する場合は、配列の最初の要素へのポインタ、たとえば2 次元配列iの行の最初の要素へのポインタと考えることができます。

2次元配列の場合、2次元配列の行のアドレスを表しますが、配列名はすでに配列の最初の要素のアドレスを表しており、実際には&a[i]同等あり、それらの値は表すものも同様です。ia[i]&a[i]

※二次元配列名[i]はi行目の先頭要素の値を取り出すもので、

※二次元配列名[i]+1はi行目の最初の要素の値を+1するもので、

※(二次元配列名[i]+1)はi+1行目から取り出した最初の要素の値を+1します

おすすめ

転載: blog.csdn.net/qq_51519091/article/details/132911841