Cポインター
C でポインターを学ぶのは簡単で楽しいものです。ポインターは C プログラミング タスクの一部のパフォーマンスを簡素化しますが、動的メモリ割り当てなどの他のタスクはポインターなしでは実行できません。したがって、優れた C プログラマーになりたい場合は、ポインターを学習する必要があります。
ご存知のように、すべての変数にはメモリ ロケーションがあり、すべてのメモリ ロケーションは、メモリ内のアドレスを表す & 演算子を使用してアクセスできるアドレスを定義します。
定義された変数のアドレスを出力する次の例を参照してください。
例:
#include <stdio.h>
int main ()
{
int var_runoob = 10;
int *p; // 定义指针变量
p = &var_runoob;
printf("var_runoob 变量的地址: %p\n", p);
return 0;
}
上記のコードをコンパイルして実行すると、次の結果が生成されます。
var_runoob 变量的地址: 0x7ffeeaae08d8
関数が複数の結果を返す必要がある場合
C言語ではパラメータの値を呼び出し先関数に渡す方法として値渡し方式を採用しているため、C言語ではメイン関数内の値を呼び出し先関数内で変更することはできませんが、メイン関数内で変数のアドレス値を渡すことができます。 to 呼び出された関数。これにより、呼び出された関数内のアドレスを介して変数の値にアクセスでき、変数の値を変更できます。
①関数値の交換例
void swap(int a,int b){
int temp;
temp=a;
a=b;
b=temp;
}
ポインター変数を使用しないと、a と b の変更された値を同時に返すことはできません; このとき、ポインターをパラメーターとして使用し、アドレスを介して変数の値にアクセスして、それを実現できます。
#include<stdio.h>
void swap(int *a,int *b){
int temp;
temp=*a;
*a=*b;
*b=temp;
}
int main(){
int a=1;
int b=3;
swap(&a,&b);
printf("a=%d b=%d",a,b);
return 0;
}
运行结果:
a=3 b=1
--------------------------------
Process exited after 0.03594 seconds with return value 0
请按任意键继续. . .
変数のアドレスが main 関数の swap 関数に渡されていることがわかります. swap 関数では、main 関数の変数の値にポインターを介して直接アクセスし、値を交換して出力しますメイン関数で交換された値。
配列とポインタ
C言語における配列とポインタの関係はとても深いのですが、具体的には以下を見てみましょう。
①aの配列を定義する
int a[5]={1,2,3,4,5};
上記の 5 つの領域に int 型のオブジェクトが 5 つ存在します。
② ポインタを宣言: int *p; ポインタに値を代入; p=&a[0];
#include<stdio.h>
int main(){
int a[]={1,2,3,4,5};
int i=0;
int *p; //声明了一个指针变量
p=&a[0]; //给指针p赋了a[0]的地址值给指针
for(i=0;i<5;i++){
printf("%d ",a[i]); //通过for循环将数组里的值打印出来了
}
printf("\n");
for(i=0;i<5;i++){
printf("%d ",*p); //第一次循环的时候通过指针访问到了a[0]的值,并输出了
p++; //对地址加1。我们第一次对地址+1得到了a[1]的地址,第二次+1得到a[2]的地址.......
}
printf("\n");
return 0;
}
运行结果:
1 2 3 4 5
1 2 3 4 5
--------------------------------
Process exited after 0.04136 seconds with return value 0
请按任意键继续. . .
③ポインタ p が格納するアドレス + 1 が a[1] のアドレスになる仕組みを探る...
出力アドレス
#include<stdio.h>
int main(){
int a[]={1,2,3,4,5};
printf("%p\n",&a[0]);
printf("%p\n",&a[1]);
return 0;
}
运行结果:
000000000062FE00
000000000062FE04
--------------------------------
Process exited after 0.04234 seconds with return value 0
请按任意键继续. . .
a[0] のアドレス空間は 000000000062FE00 であり、a[1] のアドレス空間は 000000000062FE04 です。
a[0] と a[1] のアドレス値の差が 4 であることがわかりましたが、なぜ p ポインターに格納されている値が最初は 000000000062FE00 で、+1 すると 000000000062FE01 になるのではないでしょうか? 実際、取得したのは a[1] のアドレス 000000000062FE04 であることがわかりました。
これは、p ポインタが int 型の配列の a[0] を指しているためです; p++ を実行する場合、we + a sizeof(int)=4; したがって *(p+1) は a[1 ] を指します; char 型の配列で、ポインタが p++ の場合、sizeof(char)=1 であるため、実際には 1 が加算されます。
つまり、配列の型に関係なく、ポインターに 1 を追加すると、配列内の次のオブジェクトを指すことになります。
④ポインタと配列の関係
一般的な出力:
#include<stdio.h>
int main(){
int a[]={1,2,3,4,5};
int i=0;
for(i=0;i<5;i++){
printf("%d ",a[i]);
}
return 0;
}
运行结果:
1 2 3 4 5
--------------------------------
Process exited after 0.04031 seconds with return value 0
请按任意键继续. . .
ポインター出力:
#include<stdio.h>
int main(){
int a[]={1,2,3,4,5};
int i=0;
for(i=0;i<5;i++){
printf("%d ",*(a+i));
}
return 0;
}
运算结果:
1 2 3 4 5
--------------------------------
Process exited after 0.03991 seconds with return value 0
请按任意键继续. . .
比較すると、printf("%d ",a[i]); と printf("%d ", (a+i)); ステートメントは完全に同等であることがわかりました。つまり、a[i] と書くことができます。 (a+i )のように、わかりにくいかもしれません. 実は C 言語をコンパイルするときは、まず *(a+i) に変換してから計算を行います. 実は別の言語でも理解できます.ちなみに、アドレス &a[i] とアドレス (a+i) は同じです。
ここで、配列とポインターが似ていることがわかりましたが、ポインターは変数であり、配列はそうではないことに注意してください。そして、配列を関数に渡すとき、実際に渡すのは、配列の最初の要素のアドレスです。