C言語基礎|scanf関数とポインタ

scanfで & を付ける理由、ちゃんと説明できますか?「住所を渡す」感覚が身につくと入力処理が怖くなくなる。

printf は「表示してね」と頼む関数、scanf は「ここに書き込んでね」と頼む関数。
この違いが分かると、scanf の呼び出しで変数の前に & を付ける理由がスッと理解できます。

scanf は、キーボードから読んだ値を 呼び出し側が用意した変数(オブジェクト)に格納しないといけません。
つまり、scanf には「値」じゃなくて「格納先の住所(アドレス)」を渡す必要があるんです。

この住所の箱に、入力した値を入れてください!

このお願いをするために、& を付けて住所を渡します。

printf と scanf の違い(何を渡して何をしてもらう?)

まずは対比で整理すると理解が一気にラクになります。

printf と scanf の依頼内容の違い

関数目的渡すもの依頼の言い方(イメージ)
printf画面に出すこの値を表示してください
scanf変数に入れる住所(ポインタ)この箱に書き込んでください

なぜ scanf は住所が必要?(値だけだと書き込めない)

もし scanf に「値」を渡しても、scanf から見れば「ただの数字」であって、どこに書けばいいか分かりません。
そこで住所(アドレス)を渡します。

scanf が欲しいのは格納先の場所

サンプルプログラム

入力した2つの数の合計を表示する超シンプルなプログラム例です。

プロジェクト名:chap10-8-1 ソースファイル名:chap10-8-1.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int main(void)
{
    int a, b;

    puts("2つの整数を入力してください。");

    printf("a = ");
    scanf("%d", &a);

    printf("b = ");
    scanf("%d", &b);

    printf("合計は %d です。\n", a + b);

    return 0;
}

scanf の書式(命令の書式)と何をする命令なのか

scanf は「入力を読み取って、指定された場所に格納する」関数です。

scanf の基本形

  • 書式:scanf(書式文字列, 格納先1, 格納先2, ...);

ここでいう「格納先」は多くの場合 変数のアドレスです。

例:整数を1つ読む

  • scanf("%d", &a);

意味はこうです。

  • %d:整数として読み取る
  • &a:a の住所(ここに書き込んでね)

&(アドレス演算子)を付ける理由

& は、変数の住所(アドレス)を取り出す演算子です。

& を使う場面

意味
aa の値
&aa の住所(ポインタ)

scanf は「住所」を渡してほしいので、&a が必要になります。

printf の呼び出しと scanf の呼び出し

同じ変数 i を例に、依頼の内容が違うことを見える化します。

printf の依頼(値を渡す)

printf("%d", i);

i の値が 15 なら
「15 を表示してください」

scanf の依頼(住所を渡す)

scanf("%d", &i);

i の住所が 0x1000 なら
「0x1000 の箱に整数を書き込んでください」

図のポイントはこれです。

  • printf は「読むだけ」なので値でOK
  • scanf は「書き込む」ので住所が必要

scanf の戻り値(地味に大事)

scanf は、読み取りに成功した項目数を返します。
入力エラーに強いプログラムを書くなら、ここを見るのが基本です。

scanf の戻り値

戻り値意味
11個の入力に成功
22個の入力に成功(scanf("%d%d", ...) など)
0変換に失敗(数字が必要なのに文字が来た等)
EOF入力終了(環境による)

※今回は入門として動作理解が目的なので、戻り値チェックは発展として覚えておくとOKです。

よくある間違い(& の付け忘れ)

これをやると、scanf は「書き込み先の住所」を受け取れません。結果は未定義になりやすく危険です。

NG例

scanf("%d", a);   // & がない

何が渡ってしまう?

書き方scanf が受け取るもの結果
scanf("%d", &a)a の住所正しく書き込める
scanf("%d", a)a の値(未初期化ならゴミ)どこに書くか分からず危険

空ポインタ(null pointer)と NULL

ここからは「ポインタ全体の基礎知識」として、NULL の話を整理します。

空ポインタとは

何も指さないことが保証された特別なポインタです。
「有効なオブジェクトの住所ではない」という意味で、安全な“無”の表現になります。

NULL とは

NULL は「空ポインタ」を表すための マクロです。
多くの環境でヘッダを取り込むと使えます(stdio.h でも使えることが多いです)。

NULL の位置づけ

用語意味
空ポインタ何も指さないポインタ
NULL空ポインタを表すマクロ(空ポインタ定数)

定義の一例として NULL が 0 っぽく書かれていることがありますが、プログラムでは「空ポインタとして扱う」意識が大切です。

使った表や図の説明(まとめ)

  • printf と scanf の表は「値を渡すのか、住所を渡すのか」を対比するための整理です。
  • 対比図(図A/図B)は、同じ i を使って「表示」と「書き込み」の違いを直感でつかむためのものです。
  • 戻り値表は、scanf が成功したかどうかを確認する基礎知識として追加しました。
  • NULL の表は「空ポインタ」と「NULL(マクロ)」を混同しないための整理です。