C言語ポインタ変数の定義と使い方(本質)
メモリ上の「データ」の「アドレス」も「ポインタ」になるため、変数にデータの「ポインタ」が格納されている場合、それを「ポインタ変数」と呼びます。
C 言語では、変数を使用してポインターを格納することが許可されており、この変数をポインター変数と呼びます。
「ポインタ変数の値」はデータの「アドレス」であり、そのようなデータは「配列、文字列、関数、ページの別の通常の変数またはポインタ変数」です。
ここで、文字 'K' (ASCII コードは 10 進数で 75) を格納し、アドレス OX11A (通常、アドレスは 16 進数で表現されます) のメモリを占有する「char 型変数 c」があるとします。
また、「変数 c のアドレス」と全く同じ値である OX11A を値とする「ポインタ変数 p」が存在します。この場合、「p は c を指す」または「p は へのポインタである」と言われます。ポインタ変数c」。
1. ポインタ変数を定義する
通常の変数の定義とよく似ていますが、「変数名」の前にアスタリスク * を追加します。
形式は次のとおりです。
データ型 *kankang;
または:
データ型 *kangkang = 値;
ポインタ変数: *
ポインタ変数が指すデータの型: datatype
//例えば:
int *p1;
p1 は int 型のデータを指す「ポインタ変数」であり、p1 がどのデータを指しているのかは、それに代入された値によって決まります。
例えば:
int a = 100;
int *p_a= &a;
ポインタ変数 p_a を定義するときに初期化し、それに変数 a のアドレスを代入すると、p_a は a を指します。
p_a にはアドレスが必要であることに注意してください。!!
したがって、 a の前に「アドレス文字 & を取得」を付ける必要があります。そうしないと間違いになります。!!
通常の変数と同様に、ポインターも複数回書き込むことができ、必要に応じていつでもポインター変数の値を変更できます。
詳細は以下の通り
//共通変数を定義する
浮動小数点 a = 99.5、b = 10.6;
char c = 'q',d = '#'
//ポインタ変数を定義する
float *p1 = &a;
char *p2 = &c;
//ポインタ変数の値を変更する
p1 = &b;
p2 = &d;
//知らせ!!
1. * は変数がポインタであることを示す特殊記号であり、p1 および p2 を定義する場合には * を含める必要があります。
2. p1 と p2 に「代入」する場合、コンパイラはそれがポインタ変数であることをすでに認識しているため、それ以上の操作は必要なく、ポインタ変数は通常の変数と同様に使用できます。
3. つまり、ポインタ変数を定義する場合は * を使用する必要があり、ポインタ変数に値を割り当てる場合は * を使用できません。
ポインタ変数も連続定義可能!
例えば:
int *a,*b,*c; //ポインタ abc の型はすべて int*
各変数の前に * を付ける必要があることに注意してください。次の形式で記述すると、a だけがポインタ変数となり、bc は int 型の通常の変数になります。
int *a,b,c; // a のみ int*
2. ポインタ変数によるデータの取得
ポインタ変数には「データのアドレス」が格納されており、ポインタ変数を通じて「そのアドレスのデータ」を取得することができます。
形式は次のとおりです。
*股;
*は「ポインタ演算子」と呼ばれ、アドレスのデータを取得するために使用されます。
// プログラムの例を示します
#include<stdio.h>
int main()
{
int a = 15;
int *p = &a;
printf("%d,%d\n",a,*p);
return 0;
}
結果:
15,15
aのアドレスが0X1000だとすると、pがaを指すとp自身の値も0X1000になります。*pはアドレス0X1000のデータ、つまり変数aの値を取得することを意味します。実行結果から、*p と a は同等です。
//ポインタはメモリ上のデータを取得するだけでなく、メモリ上のデータを変更することもできます。
例えば:
#include<stdio.h>
int main()
{
int a = 15,b = 99,c = 222;
int *p = &a; //定义指针变量
*p = b; //通过指针变量修改内存上的数据
c = *p; //通过指针变量获取内存上的数据
printf("%d,%d,%d,%d\n",a,b,c,*p);
return 0;
}
結果は次のとおりです。
99,99,99,99
*p は a のデータを表します。これは a と同等で、これに別のデータを代入したり、別の変数に代入したりできます。
* さまざまなシナリオでさまざまな機能があります:
1. ※ポインタ変数の定義で、これがポインタ変数であることを示すことができます(一般の変数と区別できるように)
2. 「ポインタ変数」を使用する場合は、「ポインタの指すデータを取得する」、つまり「ポインタの指すデータそのものを取得する」ことを示すために先頭に*を付けます。
つまり、「ポインタ変数を定義する場合の*」と「ポインタ変数を使用する場合の*」は全く意味が異なります。
詳細は次のとおりです。
int *p = &a;
*p = 100;
最初のコードでは、* は p がポインター変数であることを示すために使用されています。
2 番目のバンドは、ああ? * は、ポインタが指すデータを取得するために使用されます。
「注意事項」:ポインタ変数そのものを「代入」する場合、*は付加できません
次のように:
int *p;
p = &a; // ポインタ変数自体に値を代入します! !!
*p = 100;
ポインター変数は、通常の変数が出現できる任意の式にも出現できます。次に例を示します。
int x, y, *px = &x, *py = &y;
y = *px + 5; //x の内容に 5 を加算して y に代入することを示し、*px+5 は (*px)+5 と同等です
y = ++*px; //pxの内容に1を加えてyに代入、++*pxは++(*px)と同等
y = *px++; //y=*(px++)と同等
py = px; // あるポインタの値を別のポインタに代入します
誰でも理解しやすいように、以下にプログラム例を示します。
//例: ポインタを介して 2 つの変数の値を交換します。
#include<stdio.h>
int main()
{
int a = 100,b = 999,temp;
int *pa = &a;
int *Pb = &b;
printf("a=%d,b=%d",a,b);
//进入交换!!!
temp = *pa; //将a的值先保存到temp上
*pa = *pb; //将b的值交给a;
*pb = temp;//最后将保存起来的a值交给b
//结束交换,输出最终结果
printf("a=%d,b=%d\n",a,b);
return 0;
}
結果:
a=100、b=999
a=999、b=100
実行結果から、a と b の値が交換されたことがわかります。ステートメント *pa = *pb; の実行後に a の値は b の値で上書きされ、a の値が次の場合には見つからないため、一時変数 temp は非常に重要であることに注意してください。最初に保存されていません。
3. * と & に関するパズル
int 型 a があり、pa がそれらを指すポインタであるとします。では、*&a と *&pa はそれぞれ何を意味しますか?
*&a は *(&a) として理解できます。&a は「変数 a のアドレスを取得する」ことを意味し、これは (pa) と同等です。したがって、*(&a) はこのアドレス (*pa と同等) のデータを取得することを意味します。 Go を一周して元の点に戻ります。*&a は a に等しいままです。
&*pa は &(*pa) として理解できます。*pa は「pa (a に相当) が指すデータを取得する」ことを意味し、&(*pa) はデータ (&a に相当) のアドレスを表します。 *paなど。paでの価格です。
4. アスタリスク*の概要
これまでに学習した文法では、アスタリスク * には主に 3 つの用途があります。
int a = 3, b = 5, c; c = a * b; のように、最も理解しやすい乗算を示します。
int a = 100; int *p = &a; など、通常の変数と区別するためにポインター変数を定義することを示します。
int a, b, *p = &a; *p = 100; b = *p; などの間接演算である、ポインターが指すデータの取得を示します。