ポインタ(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言語の最も重要な部分であり、基本的な段階で、ポインターの学習は終了します。
次の記事では、構造の知識ポイントを学びます。