C のポインター: C プログラミングのポインターとは何ですか? 種類
⚡ スマートサマリー
C言語におけるポインタは、別の変数のメモリアドレスを格納する変数です。ポインタを用いることで、動的なメモリ割り当て、効率的な配列や文字列の処理、複雑なデータ構造の実現が可能になり、アドレス演算子や逆参照演算子を使って値の読み取りや変更を行うことができます。

C言語におけるポインタとは何ですか?
A ポインタ C言語において、ポインタは別の変数のアドレスを格納する変数です。ポインタは、別のポインタや関数を参照することもできます。ポインタは、インクリメントまたはデクリメントすることで、次のメモリ位置または前のメモリ位置を指すことができます。ポインタの目的は、メモリ領域を節約し、実行時間を短縮することです。
C でポインターを使用する方法
int型の変数vを宣言すると、vには値が格納されます。各変数は、その値の他に、メモリ上の位置を示すアドレスも持っています。アドレスは、変数名の前にアンパサンド(&)を付けることで取得できます。変数のアドレスを出力すると、実行ごとに異なる乱数のような値が表示されます。
ポインタは値を格納する代わりに、変数のアドレスを格納します。例:
int *y = &v;
| 変数 | ポインター |
|---|---|
| A 値 に保存 命名 ストレージ/メモリのアドレス。 | A 変数 それ ポイント のストレージ/メモリアドレス 別の 変数に保存します. |
ポインタの宣言
変数やポインタと同様に、 Cプログラミング ポインタは使用する前に宣言する必要があります。ポインタ宣言の形式は次のとおりです。
data_type *pointer_variable_name;
ここでは、 データ・タイプ はポインタの基本型であり、ポインタが指す変数の型を示します。乗算に使用される記号と同じアスタリスク (*) は、ポインタを宣言する間接参照演算子です。有効なポインタ宣言の例をいくつか示します。
int *ptr_thing; /* pointer to an integer */ int *ptr1, thing; /* ptr1 points to an int; thing is an int */ double *ptr2; /* pointer to a double */ float *ptr3; /* pointer to a float */ char *ch1; /* pointer to a character */
ポインタを初期化する
ポインタを宣言した後、変数アドレスで初期化します。ポインタが初期化されずに使用されると、予期しない結果が生じ、深刻な問題が発生する可能性があります。変数のアドレスを取得するには、変数名の前にアンパサンド(&)演算子を使用します。
pointer = &variable;
ポインタを説明する簡単なプログラムを以下に示します。
#include <stdio.h> int main() { int a = 10; // variable declaration int *p; // pointer variable declaration p = &a; // store address of a in pointer p printf("Address stored in p is: %x\n", p); // access the address printf("Value stored in p is: %d\n", *p); // access the value return 0; }
出力:
Address stored in p is: 60ff08 Value stored in p is: 10
| Operator | 意味 |
|---|---|
| * | 2つの目的があります。ポインタを宣言し、参照された変数の値を返します(逆参照)。 |
| & | 目的はただ一つ、変数のアドレスを返すことです。 |
C のポインターの種類
ヌルポインタ
ヌルポインタは、宣言時にNULL値を代入することで作成します。これは、ポインタにまだアドレスが割り当てられていない場合に便利です。ヌルポインタは常に0の値を保持します。
#include <stdio.h> int main() { int *p = NULL; // null pointer printf("The value inside variable p is: %x", p); return 0; }
ボイドポインタ
voidポインタ(汎用ポインタとも呼ばれる)は、標準データ型を持たない。キーワードvoidを使用して作成され、任意の変数のアドレスを格納できる。
#include <stdio.h> int main() { void *p = NULL; // void pointer printf("The size of pointer is: %d\n", sizeof(p)); return 0; }
ワイルドポインター
初期化されていないポインタはワイルドポインタと呼ばれます。これらのポインタは、未知のメモリ位置を指す可能性があり、問題を引き起こしたりプログラムをクラッシュさせたりする可能性があるため、効率的ではありません。ワイルドポインタの取り扱いには常に注意してください。
#include <stdio.h> int main() { int *p; // wild pointer printf("%d", *p); return 0; }
C言語におけるその他のポインタの種類には、ダングリングポインタ、複合ポインタ、ニアポインタ、ファーポインタ、ヒュージポインタなどがあります。
直接アクセス ポインターと間接アクセス ポインター
C言語では、変数の内容にアクセスして操作する方法は2つあります。直接アクセスでは変数名を直接使用しますが、間接アクセスでは変数へのポインタを使用します。
#include <stdio.h> int var = 1; /* declare and initialize an int variable */ int *ptr; /* declare a pointer to int */ int main(void) { ptr = &var; /* point ptr to var */ printf("\nDirect access, var = %d", var); printf("\nIndirect access, var = %d", *ptr); *ptr = 48; /* change var through the pointer */ printf("\nIndirect access, var = %d", *ptr); return 0; }
C でのポインター演算
ポインタを扱う際には、以下の優先順位ルールに従ってください。演算子 * と & は、単項演算子 (否定 !、インクリメント ++、デクリメント –) と同じ優先順位を持ちます。同じ式の中では、単項演算子 *、&、!、++、および — は右から左に評価されます。ポインタ P が変数 X を指している場合、X を記述できる場所であればどこでも *P を使用できます。以下の式は同等です。
| 表現 | 同等の表現 |
|---|---|
| Y = *P + 1 | Y = X + 1 |
| *P = *P + 10 | X = X + 10 |
| *P += 2 | X += 2 |
| ++*P | ++X |
| (*P)++ | X ++ |
最後のケースでは、括弧が必要です。単項演算子 * と ++ は右から左に評価されるため、括弧がないとポインタ P がインクリメントされ、それが指すオブジェクトはインクリメントされません。ポインタに対して使用できる算術演算は、代入、インクリメントとデクリメント、加算と減算です。trac整数オフセットを指定すると、ポインタがその要素数だけ移動します(各ステップは基本型のバイト単位のサイズに相当します)。
C言語のポインタと配列(例付き)
従来、配列要素へのアクセスにはインデックスを使用しますが、ポインタを使えば簡単にアクセスできます。配列名に設定されたポインタは、最初の要素を指します。
#include <stdio.h> int main() { int a[5] = {1, 2, 3, 4, 5}; // array initialization int *p; // pointer declaration p = a; // p points to the first element; same as &a[0] for (int i = 0; i < 5; i++) { printf("%d\n", *p); // print element p++; // move to the next element } return 0; }
ポインタに数値を加えると、その数値分だけポインタが先に移動します。例えば、pがメモリ位置0を指している場合、p + 1を加えるとポインタはメモリ位置1を指すようになります。
C のポインターと文字列と例
文字列は、ヌル文字「\0」で終わるcharオブジェクトの配列です。ポインタを使用して文字列を操作できます。
#include <stdio.h> #include <string.h> int main() { char str[] = "Hello Guru99!"; char *p; p = str; printf("First character is: %c\n", *p); p = p + 1; printf("Next character is: %c\n", *p); p = str; // reset the pointer for (int i = 0; i < strlen(str); i++) { printf("%c\n", *p); p++; } return 0; }
文字列を扱うもう一つの方法は、ポインタの配列を使うことです。
#include <stdio.h> int main() { char *materials[] = {"iron", "copper", "gold"}; for (int i = 0; i < 3; i++) printf("%s\n", materials[i]); return 0; }
C のポインターの利点
- ポインタは、メモリ上の位置に直接アクセスするのに便利です。
- これらは配列の要素に効率的にアクセスする方法を提供する。
- これらは、動的メモリの割り当てと解放に使用されます。
- これらは、連結リスト、グラフ、ツリーなどの複雑なデータ構造を形成するために使用されます。
C のポインターの欠点
- ポインタを理解するのは少し複雑です。
- これらは、セグメンテーション違反や意図しないメモリ位置へのアクセスといったエラーを引き起こす可能性があります。
- ポインタに誤った値を指定すると、メモリ破損を引き起こす可能性があります。
- メモリが解放されない場合、ポインタもメモリリークの原因となる。
- ポインタを慎重に扱うのはプログラマの責任である。
