C言語の基礎

void save(const char *input) {
    char name[8];
    strcpy(name, input);
    printf("%s\n", name);
}

上の関数 save に、8文字の文字列 "ABCDEFGH" を渡した。起こることとして正しいものはどれか。

  1. A終端の '\0' を含めて9バイトが書き込まれ、name の外側の1バイトを壊す(未定義動作)
  2. Bちょうど8文字なので name に収まり、ABCDEFGH と正しく表示される
  3. Cstrcpy が name の大きさに合わせて7文字に切り詰め、最後の要素に終端の '\0' を入れる
答えと解説を見る

正解:A. 終端の '\0' を含めて9バイトが書き込まれ、name の外側の1バイトを壊す(未定義動作)

文字列 "ABCDEFGH" は、終端の '\0' を含めると9バイトです。strcpy は書き込み先の大きさを知らずに '\0' までをすべて写すので、8バイトの name の外側に1バイトはみ出して書き込みます(バッファオーバーフロー)。はみ出した分はスタック上のほかの変数や戻り先の番地を壊すことがあり、外から長い入力を与えて任意のコードを実行させる攻撃にも使われます。snprintf(name, sizeof name, "%s", input) のように、書き込む大きさを指定できる関数を使って防ぎます。

  • A. 正しい。9バイト目の '\0' が配列の外に書き込まれます。
  • B. 8文字の文字列には、終端の '\0' を含めて9バイトが必要です。
  • C. strcpy は書き込み先の大きさを知らないので、切り詰めることはしません。
この分野を解く 分野ページへ

C言語の基礎の参考書を探す PR

Amazonの検索結果へのリンクです。Amazonのアソシエイトとして、半導体教室は適格販売により収入を得ています。

C言語の基礎のほかの問題

  1. C言語で NULL ポインタを参照した(p が NULL のときに *p を読んだ)ときの説明として、正しいものはどれか。
  2. char は1バイト、int は4バイトで、int を4の倍数の番地にそろえて置く一般的な環境とする。上のコードを実行したときの出力として、正しいものはどれか。
  3. uint32_t は32ビット、uint8_t は8ビットの符号なし整数型で、リトルエンディアンの環境とする。上のコードを実行したときの出力として、正しいものはどれか。
  4. 3ビットのビットフィールドに9を入れる上のコードを実行したときの出力として、正しいものはどれか。
  5. #define で定義したマクロ SQUARE を使う上のコードを実行したときの出力として、正しいものはどれか。