[C言語の基礎11-ポインタ(2)]


序文

この記事は、前の内容を継続し、ポインター関連の知識ポイントについて学習し続けます。


4.ポインタ操作

  • ポインタ±整数
  • ポインタ-ポインタ
  • ポインタの関係演算

4.1ポインタ±整数

#define VALUE 5
int main()
{
    
    
	float values[VALUE];
	float *vp;
	//指针+-指针,关系运算
	for (vp = &values[0]; vp < &values[VALUE];)
	{
    
    
		*vp++ = 0;//通过这样完成初始化
	}
	for (int i = 0; i < VALUE; i++)
	{
    
    
		printf("%d ", values[i]);
	}
	return 0;
}

ここに画像の説明を挿入

4.2ポインター-ポインター

int main()
{
    
    
	int arr[10] = {
    
     0 };
	printf("%d\n", &arr[9] - &arr[0]);//得到元素的个数
	printf("%d\n", sizeof(arr)/sizeof(arr[0]));//计算元素个数
	int* p0 = &arr[0];
	int* p9 = &arr[9];
	printf("%d\n", (p9 - p0));//得到元素的个数
	return 0;
}

配列の最初と最後の要素のアドレスを引くことにより、配列内の要素の数が取得されます。

-int *は、ポインタが指すアドレスを示します。格納されるデータ型は整数であり、4バイトを占めます。

  • 配列要素+1のアドレスは、次の要素のアドレスを見つけるためのものであり、4バイト移動します
    ここに画像の説明を挿入
    。この現象は、デバッグを通じてより明確に観察されます。int配列の各要素は4バイトを占めます。
  • &arr [0]:0x005cf7f8
  • &arr [0] +1:0x005cf7fc、アドレスが1ビット移動します。つまり、int *ポインタが1ビット移動し、バイトが4増加します。
    ここに画像の説明を挿入
    前提条件:両方のポインターが同じスペースを指している必要があります
char ch[5];
int arr[6];
%arr[4]-&ch[3];//错误的

前回の記事では、2つの方法で文字列の長さの方法を紹介しました。

  • サイクル
  • 再帰

ここでは、3番目の方法であるポインターを紹介します。

int mylen(char* pa)//传参是数组首元素的地址
{
    
    
	char* p = pa;//首元素地址
	while (*pa)//元素不是‘0’
	{
    
    
		pa++;//通过地址访问字符串
	}
	//结尾字符0的地址减首元素地址
	return pa - p;//指针相减是元素的个数
}
int main()
{
    
    
	char arr[] = "abcdef";
	int len = mylen(arr);
	printf("%d", len);
	return 0;
}

4.3ポインタの関係演算

標準の状態:配列要素へのポインタは、配列の最後の要素の後のメモリ位置へのポインタと比較でき
ますが、最初の要素の前のメモリ位置へのポインタとの比較はできません。

int main()
{
    
    
	//
	for (vp = &values[5]; vp > &values[0];)
	{
    
    
		*--vp = 0;
	}
	for (vp = &values[5-1]; vp >= &values[0];vp--)//不允许
	//地址会指向首元素前面的地址,这是不允许的
	{
    
    
		*vp = 0;
	}
	return 0;
}

5.ポインタと配列

int main()
{
    
    
	int arr[10] = {
    
    1,2,3,4,5,6,7,8,9,0};
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
	int *p = arr;//p存放的是数组首元素的地址
	return 0;
}

配列名は、配列の最初の要素のアドレスと同じです。配列名は、配列の最初の要素のアドレスを表します。(2つの場合を除いて、配列シリーズの記事を詳しく紹介します)
ここに画像の説明を挿入
配列名はアドレスとしてポインタに格納できるため、ポインタを使用してアクセスすることができます。

int main()
{
    
    
	int arr[] = {
    
    1,2,3,4,5,6,7,8,9,0};
	int *p = arr; //指针存放数组首元素的地址
	int sz = sizeof(arr)/sizeof(arr[0]);
	for(int i=0; i<sz; i++)
	{
    
    
		printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p+i);
	}
	return 0;
}

ここに画像の説明を挿入
上の図を観察してください。したがって、p + iは、配列arr内のインデックスがiである要素のアドレスを実際に計算します。次に、ポインタを介して配列に直接アクセスできます。

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

ここに画像の説明を挿入

6.セカンダリポインタ

ポインタ変数も変数であり、変数にはアドレスがあります。ポインタ変数のアドレスはどこに保存されていますか?これはセカンダリポインタです

int main()
{
    
    
	int a = 10;
	int* pa = &a;
	int** ppa = &pa;
	return 0;
}
  • aのアドレスは、第1レベルのポインターであるポインターpaに格納されます。
  • paのアドレスは、セカンダリポインタであるppaに格納されます。
    ここに画像の説明を挿入

セカンダリポインタの操作は次のとおりです。

  • * ppaはppaのアドレスを逆参照してpaを検索し、*ppaは実際にpaにアクセスします。
int b = 20;
*ppa = &b;//等价于 pa = &b;
  • **ppaは最初に*ppaを介してpaを検索し、次にpaを逆参照します:* pa、これは
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

7.ポインタの配列

ポインターの配列はポインターですか、それとも配列ですか?

  • は配列です。ポインタの配列です

配列シリーズの記事では、整数配列、文字配列が導入されています。

int arr1[5];//占用20个字节
char arr2[5];//占用5个字节

ここに画像の説明を挿入

7.1例1

ポインタの配列:

int main()
{
    
    
	int data1[] = {
    
     1,2,3,4,5 };
	int data2[] = {
    
     2,3,4,5,6 };
	int data3[] = {
    
     3,4,5,6,7 };
	//看成二维数组
	int* arr[3] = {
    
     data1,data2,data3 };
	for (int i = 0; i < 3; i++)
	{
    
    
		for (int j = 0; j < 5; j++)
		{
    
    //[]是操作符
			printf("%d ", arr[i][j]);//不需要解引用
		}
		printf("\n");
	}
	   
	return 0;
}

arr3は5つの要素を持つ配列であり、各要素はアドレスである整数ポインターです。

  • 要素data1であるarr[0]はポインター変数であり、それ自体が1次元配列{1,2,3,4,5}の配列名であり、最初の要素のアドレスを表します。
  • 要素data2であるarr[1]はポインター変数であり、これは1次元配列{2,3,4,5,6}の配列名でもあり、最初の要素のアドレスを表します。
  • 要素data3であるarr[2]はポインター変数であり、それ自体が1次元配列{3,4,5,6,7}の配列名であり、最初の要素のアドレスを表します。

ここに画像の説明を挿入
ここに画像の説明を挿入
また、デバッグによって見つけることもできます。

  • ポインター配列の最初の要素であるdataは、ポインター変数であり、1次元配列の最初の要素のアドレスです。
  • 配列内の要素には、配列名+iでアクセスできます。
  • ポインターの配列は、2次元配列として表示できます。
arr[0]=data1;//指针数组首元素data,是指针变量,也是一维数组首元素的地址
arr[0][0]=data1[0];//看成一维数组
arr[0][1]=data1[1];
arr[0][2]=data1[2];
arr[0][3]=data1[3];
arr[0][4]=data1[4];

ここに画像の説明を挿入
印刷結果を次の図に示します。
ここに画像の説明を挿入
コードは次の効果に置き換えられ、アドレスの間接参照の観点から記述されています。

int main()
{
    
    
	int data1[] = {
    
     1,2,3,4,5 };
	int data2[] = {
    
     2,3,4,5,6 };
	int data3[] = {
    
     3,4,5,6,7 };
	//看成二维数组
	int* arr[3] = {
    
     data1,data2,data3 };
	for (int i = 0; i < 3; i++)
	{
    
    
		for (int j = 0; j < 5; j++)
		{
    
    
			printf("%d ", *(arr[i]+j));//地址访问解引用
		}
		printf("\n");
	}   
	return 0;
}

ここに画像の説明を挿入

7.2例2

ポインタ配列の要素は、アドレスであるポインタ変数です。

int main()
{
    
    
	int a = 10;
	int b = 11;
	int c = 12;
	int d = 13;
	int e = 14;
	int* arr[5] = {
    
     &a,&b,&c,&d,&e };//指针数组存放的元素是指针变量,就是地址
	for (int  i = 0; i < 5; i++)
	{
    
    
		printf("%d ", *(arr[i]));//地址解引用
	}
	return 0;
}

ここに画像の説明を挿入


要約する

この記事では、ポインターに関連する知識のポイントを引き続き学習します。ポインターはC言語の最も重要な部分であり、基本的な段階で、ポインターの学習は終了します。

次の記事では、構造の知識ポイントを学びます。

おすすめ

転載: blog.csdn.net/taibudong1991/article/details/123963476