C言語-ポインタ上級3-配列ポインタ

配列ポインタの定義

類推:

整数ポインタ-- 整数へのポインタ

int a = 10;
int* pa = &a;

文字ポインタ-- 文字へのポインタ

char ch = 'a';
char* pc = &ch;

配列ポインタ -- 配列へのポインタ

int arr[10] = { 0 };
int(*p)[10] = &arr; // 数组指针

違い: ポインタ配列と配列ポインタ

int(*p1)[10]; // 数组指针
int* p2[10];  // 指针数组

p1 は最初に * と結合され、p がサイズ 10 の整数の配列を指すポインター変数であり、すべての p1 が配列を指すポインターであり、p1 が配列ポインターであることを示します。

p2 は int* 型を格納する 10 個の要素を持つ配列であり、p2 はポインタの配列です。

注: [ ] は * よりも優先され、() を使用して p1 と * を最初に組み合わせる必要があります。

配列名と&配列名

ほとんどの場合、配列名は配列の最初の要素のアドレスですが、2 つの例外があります。

1 & 配列名、配列名は配列全体を表します

2 sizeof (配列名)、配列名は配列全体を表し、配列全体のサイズが計算されます。

int arr[10];

上記の配列の場合、arr と &arr は何を意味しますか?

arr は配列名であり、配列名は最初の要素のアドレスを表すことがわかっています。&arr が arr と同じかどうかは、まず次のコードを見てください。

int main()
{
	int arr[10] = { 0 };
	printf("arr = %p\n", arr);
	printf("&arr= %p\n", &arr);

	return 0;
}

操作結果:

&arr と arr が同じアドレスを出力していることがわかりますが、これは arr と同様に配列の最初の要素のアドレスを表すのでしょうか? 次のコードを見てください。

int main()
{
	int arr[10] = { 0 };
	printf("arr = %p\n", arr);
	printf("&arr= %p\n", &arr);
	printf("arr+1 = %p\n", arr + 1);
	printf("&arr+1= %p\n", &arr + 1);

	return 0;
}

操作結果:

&arr と arr は同じ値ですが、意味は異なるはずであることがわかります。実際、&arr は配列全体のアドレスを表します。この例では、&arr の型は int(*)[10] であり、配列ポインター型です。&arr+1 は配列全体のサイズを 40 オフセットし (アドレスは 16 進数で表示されます)、arr+1 は整数サイズだけオフセットします。

したがって、配列名と&配列名は値は同じでも意味は同じではなく、一方が配列の先頭要素のアドレス、もう一方が配列のアドレスであることが分かります。配列の最初のアドレスです。本質は、それらの型が異なり、1 つは同じ型のポインターであり、もう 1 つは配列ポインターであるということです。

配列ポインターと配列名の概念を理解したところで、(ポインター) 配列ポインターの型がどのようなものかを見てみましょう。

int* arr[10]; // (整型)指针数组
int* (*p)[10] = &arr; // (整型指针)数组指针

配列ポインタの使用

はじめに -- 1 次元配列へのポインタ アクセス

次のように、添字またはポインターを介して配列にアクセスできることがわかっています。

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	// 下标访问数组
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	// 指针访问数组
	int* p = arr;
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));//*(p+i)与p[i]等价
	}

	return 0;
}

操作結果:

2次元配列への配列ポインタアクセス

    int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };

添え字を介して 2 次元配列にアクセスします。

int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}

	return 0;
}

操作結果:

arr[i] は実際には配列の各行の最初の要素のアドレスであり、arr[i][j] は *(arr[i]+j) と同等です。2 次元配列の場合、その最初の要素は配列の最初の行であり、その配列名は配列の最初の行のアドレス (配列ポインター) です。ポインターを使用して 1 次元配列にアクセスするのと同様に、配列ポインターを定義して 2 次元配列にアクセスできますが、これは配列ポインターの実際の用途ではありません。

配列ポインターの主な用途の 1 つは、2 次元配列をパラメーターとして受け取ることです。次に例を示します。

void print_arr(int(*arr)[3], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
    int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	print_arr(arr, 3, 3);

    return 0;
}

操作結果:

2 次元配列名を理解する:

実際、2 次元配列パラメータ (int arr[][3]) を渡す本質は、2 次元配列の配列名である配列ポインタを渡すことです。配列パラメータの受け渡しとポインタパラメータの受け渡しについては、次の記事で詳しく説明します。

高度なポインターの内容を学習し続けます。次の記事「配列パラメーター/ポインター パラメーター」を参照してください。

おすすめ

転載: blog.csdn.net/2301_79391308/article/details/132995096