
【6日でできるC言語入門】scanf関数とポインタ変数
C言語の入力処理でよく利用される関数が scanf です。scanf では、数値型や文字列型の入力時に「&(アドレス演算子)」を付けたり付けなかったりする書き方が登場します。なぜそのような違いが生まれるのか?その謎を解くカギは、「ポインタ」と「配列」の関係性にあります。ここでは、scanf とポインタ変数の関係を、図表や具体的なC言語プログラムを交えて徹底解説します。

1.scanf関数の基本とアドレスの意味
1.1. scanf関数と数値入力
数値型変数へ値を入力する場合、scanf の第2引数には「変数のアドレス」を渡します。これは、scanf がそのアドレスに入力値を書き込むためです。
サンプルプログラム1:整数の入力と表示
プロジェクト/ファイル名: Lesson55_1/main.c
#include <stdio.h>
int main(void) {
int age;
printf("年齢を入力してください:");
scanf("%d", &age); // &ageで「ageのアドレス」を渡す
printf("あなたの年齢は%d歳です。\n", age);
return 0;
}実行結果
「SDLチェック」を「いいえ」にして、プログラムを実行します。
年齢を入力してください:25
あなたの年齢は25歳です。解説&age は「ageのアドレス(格納先)」を指します。scanf はそのアドレスに、ユーザーが入力した値(ここでは25)を書き込みます。
1.2. scanf関数と文字列入力
文字列(char型配列)に値を入力する場合は、配列名だけでOKです。
サンプルプログラム2:名前(文字列)の入力と表示
プロジェクト/ファイル名: Lesson55_2/main.c
#include <stdio.h>
int main(void) {
char name[20];
printf("お名前を入力してください:");
scanf("%s", name); // nameは配列の先頭アドレス
printf("こんにちは、%sさん!\n", name);
return 0;
}実行結果
「SDLチェック」を「いいえ」にして、プログラムを実行します。
お名前を入力してください:さくら
こんにちは、さくらさん!解説name は配列の名前であり、「nameの先頭アドレス」を示します。
つまり、scanf("%s", name) と書くことは、scanf("%s", &name[0]) と同じ意味になります。
1.3. アドレス渡しの違いを表で比較
| 入力値の種類 | scanfの書き方 | アドレスの渡し方 | ポインタとの関係 |
|---|---|---|---|
| 整数/実数変数 | scanf("%d", &a); | 変数のアドレスを渡す | &aはint *型のポインタ |
| 文字列(配列) | scanf("%s", s); | 配列の先頭アドレス | sはchar *型のポインタ |
| 配列の要素 | scanf("%d", &arr[0]); | 要素のアドレス | &arr[0]はint *型のポインタ |
2.ポインタと配列の関係性を図で理解
2.1. 配列名とアドレスの関係
配列名(例えば name)は、配列の「先頭アドレス」を意味します。
イメージ図
char name[5];
name ──→ | n | a | m | e | \0 |
↑
&name[0]ここで、name も &name[0] も、実は同じアドレスを指しています。
2.2. scanf関数とポインタの型
- 整数の入力例:
scanf("%d", &n);・・・&nはint型変数nのアドレス、つまりint型ポインタ(int *型)。 - 文字列の入力例:
scanf("%s", s);・・・sはchar型配列の先頭アドレス、つまりchar型ポインタ(char *型)。
このように、どちらも「ポインタ」を渡している、という点がポイントです。
2.3. ポインタ変数とscanfの連携
サンプルプログラム3:ポインタ変数を利用した入力
プロジェクト/ファイル名: Lesson55_3/main.c
#include <stdio.h>
int main(void) {
double num;
double *p = # // numのアドレスをポインタ変数pに格納
printf("小数を入力してください:");
scanf("%lf", p); // ポインタ変数を使ってアドレスを渡す
printf("入力した値は%.2fです。\n", num);
return 0;
}実行結果
「SDLチェック」を「いいえ」にして、プログラムを実行します。
小数を入力してください:3.14
入力した値は3.14です。解説scanf の第2引数は、double * 型(アドレス)を要求しています。ポインタ変数 p を渡すことで、numの格納先として利用できます。
3.注意点と実用例
3.1. 配列(文字列)の時だけアドレス演算子が不要な理由
配列名は「先頭アドレス」を直接意味するため、& を付けると「二重ポインタ」になってしまいます。
例:scanf("%s", &name); は正しく動作しない場合があるので注意しましょう。
3.2. 配列の各要素をscanfで入力する方法
サンプルプログラム4:複数要素の入力
プロジェクト/ファイル名: Lesson55_4/main.c
#include <stdio.h>
int main(void) {
int data[3];
printf("整数を3つ入力してください:\n");
for (int i = 0; i < 3; i++) {
scanf("%d", &data[i]);
}
printf("入力された値:%d, %d, %d\n", data[0], data[1], data[2]);
return 0;
}実行結果
「SDLチェック」を「いいえ」にして、プログラムを実行します。
整数を3つ入力してください:
7 8 9
入力された値:7, 8, 9まとめ
scanf 関数の第2引数には「入力値を書き込むためのアドレス(ポインタ)」を渡す必要があります。
数値型の場合は&を付けて変数のアドレスを、文字列(配列)の場合は配列名そのもの(=先頭アドレス)を指定するのがルールです。
この仕組みと理由を理解することで、C言語の「ポインタ」と「配列」の根本的な関係性を自然に身につけることができます。今後のプログラム作成でも大いに役立つ知識となるでしょう。
