C/C++学習 · 4 min read · Oct 11, 2025
C/C++を段階的に学ぶ - ページ9
09. 段階的C/C++ — Cプログラミング - ポインタ
ポインタ
| | 1. メモリについて
- アドレッシング方式
- 変数のアドレスを見つける方法
- ポインタ
- ポインタ算術
- ポインタと配列
- ポインタと文字列
- 用語集 |
1. メモリについて
コンピュータはデータを保存し、操作する機能を持っています。データの保存には、データを迅速かつ正確に混乱なく保存および取得できるストレージデバイスが必要です。一般的にコンピュータは2つのストレージ方法で妥協しなければなりません。
| | |
SRAM 静的ランダムアクセスメモリ
DRAM 動的ランダムアクセスメモリ
EEPROM 電気的に消去可能なプログラム可能な読み出し専用メモリ
メモリチップはデータ、命令、および中間および最終結果を保存できます。メモリはバイト単位で整理されており、各バイトは1文字の情報を保存できます。メモリの各バイトにはアドレスまたは位置番号があり、これにより一意に識別されます。メモリのサイズはキロバイト(KB)、メガバイト(Mb)、ギガバイト、またはテラバイト(TB)で測定されます。
RAM:
メモリデバイスは情報を保存するためのストレージ場所です。
重要なコンピュータリソースメモリは、Cプログラム内での宣言後に各変数に割り当てられます。変数の型は、各変数に割り当てられるメモリのバイト数を決定します。
| |
|
2. アドレッシング方式
| |
|
上の図は次の情報を示しています。
| | 1. RAMは一時的なメモリであり、コンピュータの一部です。
- プログラムの値を保持できます。
- RAMの各バイトは、アドレスと呼ばれる一意の正の数で識別されます。
- アドレスは、通りの家の番号のように数字です。
- 数字は0から始まり、1-2-3と続きます。
- 640 KBのメモリがある場合、最高アドレスは655,359であり、1MBのメモリの場合は1,048,575です。
- プログラムがメモリにロードされると、これらのアドレスの特定の範囲を占有します。
- つまり、プログラム内のすべての変数とすべての関数は特定のアドレスから始まります。 |
3. 変数のアドレスを見つける方法
前のセクションのポイント8は、すべての変数/関数が特定のアドレスから始まることを示しています。アドレスは16進数形式の一意の正の数です。
変数のアドレスを見つけることは、演算子&(アドレスオブ)を使用することで簡単に行えます。
&(アドレスオブ) - 現在のプログラム内の変数/関数のアドレスを教えてくれます。
次のプログラムは、変数‘a’のアドレスを見つける方法を示しています。
| | / 58_address.c /
#include
int main()
{
int a = 10;
printf(“\n Aの値は: %d”, a);
printf(“\n Aのアドレスは: %d”, &a);
return 0;
} |
上記のマークされた形式の値を次の形式に置き換えて、絶対的な16進数アドレス値を取得します。
0x%x
例
printf("\nAのアドレスは: 0x%x", &a);関数‘disp()’のアドレスを見つけるプログラム
| | / 59_address.c /
#include
void disp()
{
printf(“\nこんにちは”);
printf(“\nお元気ですか”);
printf(“\nあなたは”);
} int main()
{
disp();
printf(“\n disp()のアドレス: 0x%x”, &disp);
return 0;
} |
4. ポインタ
前のセクションでは、変数/関数のアドレスを見つけて表示する方法を知っています。
今回は、変数/関数のアドレスを別の変数に保存する方法を学びます。
注意: 変数は定数値を保持できます。
| | 次のように試してください: int a, b;
a = 5; / 有効 /
b = &a; / 無効 / 再度次のように試してください: int a, b;
a = 5; / 有効 /
b = &a; / 有効 */ |
b = &a; 正解! はい、変数(一般変数)はアドレスを保持できません。しかし、‘*’(ポインタ変数)で始まる変数は、定数値と他の変数/関数のアドレスの両方を保持できます。
ポインタ: アドレス値を保持する変数。
| | 変数(一般)
一般変数は定数値を保持するための1つの操作のみを実行します | ポインタ変数(‘*’で始まる変数)
ポインタ変数は、定数値と他の変数/関数のアドレス値の両方を保持するための2つの操作を実行できます |
アドレスへの参照 / ポインタへの参照 / アドレスの内容 (*)
int *ptr;初心者には、これはかなり奇妙な構文です。アスタリスクはポインタを意味します。したがって、この文は変数ptrをintへのポインタとして定義します。これは、変数が整数変数のアドレスを保持できることを意味する別の方法です。
| | もし私たちがそれをポインタ型と呼ぶなら、次のように宣言を書くことができます。
ポインタ ptr; /* 無効 */
``` 問題は、コンパイラがポインタが指す変数の種類を知る必要があることです。 |
| | ポインタ変数の宣言
char *cptr; /* 文字へのポインタ */
int *iptr; /* intへのポインタ */
float *fptr; /* floatへのポインタ */
struct emp *e; /* 抽象データemp eへのポインタ */ |
#### ポインタが指す変数へのアクセス:
ここでは、名前の代わりにアドレスを使用して変数の値にアクセスする特別な方法があります。
| | /* 60_addr.c */
#include
int main()
{
int var1 = 11; /* 変数var1 = 11 */
int *ptr; /* ポインタとしての変数ptr */
ptr = &var; /* varのアドレスをptrに保持 */
printf("var1の値は%dです", *ptr); /* var1のアドレスへのポインタ */
return 0;
} |
| |  |
もし文がprintf("%d", ptr);であれば、ptrの値、つまりvar1のアドレスを表示しますが、上記の文は、変数ptrに保存されたアドレスの内容を表示できます。
アドレスオブとポインタの使用を示すプログラム
| | /* 61_ptrdemo.c */
#include
int main()
{
int a = 10, *p; /* 整数aとポインタp */
p = &a; /* aのアドレスをpに割り当て */
printf("\nAの値: %d", a); /* aの内容 */
printf("\nAのアドレス: 0x%x", &a); /* aのアドレス */
printf("\nPの値: 0x%x", p); /* pの内容 */
printf("\nPのアドレス: 0x%x", &p); /* pのアドレス */
printf("\n aのアドレスの内容: %d", *p); /* &aへのポインタ */
return 0;
} |
#### 5. ポインタ算術
すべての変数は算術演算をサポートできますが、ポインタにも算術演算を行うことができます。C/C++言語は、ポインタに対して4つの算術演算をサポートしています。
| | 操作
加算
減算
インクリメント
デクリメント | 記号
+
-
++
-- |
注意: ポインタ算術の主な特徴は、上記の演算子がその変数型に関連してバイト単位であることです。
| | /* 62_ptr.c */
/* ポインタ算術のデモンストレーション */
#include
int main()
{
int a, *p;
a = 100;
p = &a;
(*p)++; /* アドレスの内容を1増加 */
printf("%d", *p);
return 0;
} |
| | 出力
101 |
ポインタ算術のデモンストレーション、アドレス値をインクリメント
| | /* 63_ptr.c */
/* アドレス値を1増加 */
#include
int main()
{
int a, *p;
a = 100;
p = &a;
*p++; /* pのアドレス値を1増加 */
printf("%d", *p);
return 0;
} |
| | 出力
予期しない出力 |
上記のプログラムは、値とアドレスのインクリメントに関する算術演算子を示しています。pはポインタ変数であり、aは100に割り当てられ、pはaのアドレスに割り当てられています。
今*p++は、実際には2バイトのメモリをスキップして新しいアドレスを取得し、その内容を取得します。
もしそれが**(*p)++**であれば、pが指す内容である100がインクリメントされ、101になります。
#### 6. ポインタと配列
C/C++言語では、データ型ポインタと配列は互いに似ています。配列要素の参照とポインタ変数の両方が、メモリ内のデータ要素のアドレスを保持するために使用されます。
| | char name[20];
または
char *name ;
char months[12][10];
または
char **months; |
ポインタと配列の間には密接な関連があります。ここで配列についてのレビューがあります。
| | /* 64_ptrarr.c */
#include
int main()
{
int i, a[5] = { 56, 43, 78, 98, 12 };
for( i = 0; i < 5; i++)
printf("\n%d", a[i]);
return 0;
} |
ポインタ表記を使用して配列要素にアクセスする可能性があります。
次のプログラムの出力を見つけてください。
| | /* 65_ptrarr.c */
#include
int main()
{
int i, a[5] = { 56, 43, 78, 98, 12 };
for( i = 0; i < 5; i++)
printf("\n%d", *(a+ i) );
return 0;
} |
次のプログラムに従ってください。
| | /* 66_ptrarr.c */
#include
int main()
{
int i, a[ ] = { 56, 43, 78, 98, 12 }, *p;
p = a;
for( i = 0; i < 5; i++)
printf("\n%d", *(p+ i) );
return 0;
} |
与えられた配列の要素を印刷する最も簡単な方法です(サイズは必要ありません)。
| | /* 67_ptrarr.c */
#include
int main()
{
int i, a[ ] = { 56, 43, 78, 98, 12 }, *p;
p = a;
while (*p) /* または for(int i = 0; i<5; i++ ) */
printf("\n%d", *p++);
return 0;
} |
#### 7. ポインタと文字列
文字列は、スペースを含む文字のコレクションです。今回は、ポインタを使用して文字列を処理する方法について説明します。混乱を避けるためのさらなる議論はありません。ポインタと文字列の配列の両方を検証するための簡単なタスクです。
文字列とポインタの間には微妙な違いがあります。プログラムに従ってください。
| | /* 68_ptrstr.c */
#include
int main()
{
char str1[ ] = "Cを探求したいと思います。";
char *str2 = "Cを探求したいと思います。";
puts(str1);
puts(str2);
str1++; /* 無効な式 */
str2++; /* 有効な式 */
puts(str2); /* ou would like to……を印刷 */
return 0;
} |
関数引数としての文字列
ポインタ変数は配列変数よりも柔軟です。ここでは、ポインタ表記で文字列を表示するプログラムを示します。
| | /* 69_ptrarr.c */
#include
void disp(char *p);
int main()
{
char str[ ] = "こんにちは!!..こんにちは!!..ポインタはそれを処理できますか?";
disp(str);
return 0;
} void disp(char *p)
{
while(*p)
printf("%c", *p++);
} |
文字列のポインタの配列
文字列の配列を保存するには、サブ配列がすべて同じ長さでなければならないという欠点があります。したがって、文字列がサブ配列よりも短いときにスペースが無駄になります。ここに解決策があります。
| | /* 70_strings.c */
#include
int main()
{
char *weeks[7 ] = { "日曜日", "月曜日", "火曜日", "水曜日",
"木曜日", "金曜日", "土曜日" };
int i;
for( i = 0; i<7; i++)
puts(weeks[ i ] );
return 0;
} |
文字列が配列の一部でない場合、C/C++はそれらをメモリ内に連続して配置します。したがって、無駄なスペースはありません。
**/* 整数型のポインタの配列を保持する例プログラム */**
| | /* 71_ptrarr.c */
#include
int main()
{
int *arr[4]; /* 整数ポインタの配列 */
int i = 31, j = 5, k = 19, l = 71, m;
arr[0] = &i;
arr[1] = &j;
arr[2] = &k;
arr[3] = &l;
for(m = 0; m <= 3; m++)
printf("\n%d", *(arr[m]) );
return 0;
} |
ライブラリ関数の概要
私たちはすでに標準の文字列関数に慣れています。これらはポインタ表記を使用して指定された文字列引数を持っています。
ポインタと文字列の概念が明確であれば、自分自身の文字列関数を書くことができます。
ここに文字列をコピーする例プログラムがあります。
**/* ポインタを使用して1つの文字列を別の文字列にコピー */**
| | /* 72_strcpy1.c */
#include
void strcpy1(char * dest, char *src);
int main()
{
char *str1 = "C/C++についてもっと学ぶにはどうすればよいですか!!!";
char *str2;
strcpy1(str2, str1);
puts(str2);
return 0;
} void strcpy1(char * dest, char *src)
{
while(*src)
*dest++ = *src++;
*dest = '\0';
} |
#### 8. 用語集
| アドレス | メモリ内の位置を指す値。ポインタは値自体ではなく、値のアドレスまたは位置を含みます。 |
| 配列 | 配列は同じ型のデータ項目のコレクションです。 |
| 連続的 | 値がメモリまたはディスク上の連続した位置に保存されることを指定するストレージの特性。 |
| 関数 | 特定のタスクを実行するための命令の一連であり、他の関数と組み合わせてプログラムを作成できます。 |
| メモリ | データを受け入れ、保持し、後で要求に応じて提供できるデバイスまたはメディアを説明します。ストレージと同義です。 |
| ポインタ | 値自体ではなく、値のアドレスまたはメモリ位置を含みます。 |
| RAM | (ランダムアクセスメモリ) 1. データの物理的な位置によってデータの取得に必要な時間が大きく影響されないように構造化されたストレージデバイス。 2. パーソナルコンピュータの*主要ストレージセクション*。 |
| 文字列 | 0個以上の文字を保存できる配列。Cでは、文字列はNULL(\0)文字を追加して文字配列として宣言され、文字列の終わりを指定します。 |
| 変数 | プログラムの実行中に値が変化する可能性のあるメモリ内の位置に関連付けられた名前。 | 新しい投稿を受信箱で受け取る
スパムはありません。いつでも購読を解除できます。