コース一覧
    C言語中級 文字列・構造体
    strcpyを自作する

    C言語中級 文字列・構造体

    C言語の文字列と構造体を学び、複数のデータを整理して扱うコースです。

    1
    文字列処理の実践
    01. strlenを自作する15分
    02. strcpyを自作する15分
    03. バッファオーバーフロー体験15分
    04. 文字列を分解する15分
    05. 動的な文字列15分
    06. つくる 名前入力の安全化15分
    07. 第3章クイズ10分
    2
    構造体とポインタ
    01. 構造体ポインタと->15分
    02. 構造体の動的確保15分
    03. 動的な構造体配列15分
    04. 関数ポインタ15分
    05. qsortで並べ替える15分
    06. つくる 動的Student完成15分
    07. 第4章クイズ10分

    strcpyを自作する

    代入では文字列は写らない

    前回で、文字列の終わりが '\0' で決まっていることを見ました。今回はその文字列を別の場所へ写します。

    まず、うまくいかない書き方から確かめます。

    c

    char name[64] = "Tanaka";
    char copy[64];
    copy = name;   /* コンパイルエラー */

    配列そのものを代入することはできません。では次はどうでしょうか。

    c

    char *p = name;

    これは通りますが、写したことにはなりません。p は name の先頭を指しているだけで、中身は1バイトも増えていません。p[0] = 'X'; と書けば name のほうが変わります。同じ実体を2つの名前で見ているだけだからです。

    本当に別の場所へ持ちたいなら、1バイトずつ運ぶしかありません。それをやってくれるのが strcpy です。

    strcpy の中身

    c

    void my_strcpy(char *dest, const char *src) {
        while (*src != '\0') {
            *dest = *src;
            dest++;
            src++;
        }
        *dest = '\0';
    }

    やっていることは、読む側と書く側の2本のポインタを同時に進めながら、1バイトずつ写すことだけです。前回と同じ歩き方が、今度は2本になっただけとも言えます。

    見落としやすいのが最後の *dest = '\0'; です。while は src が終端に来た時点で抜けるので、終端そのものは写されていません。ここを書き忘れると、copy の中身は正しく並んでいるのに終わりの印が無い状態になり、表示すると後ろのごみまで続けて出ます。しかも運が良ければ動いてしまうので、気付きにくい壊れ方をします。

    dest に const が付いていないのは、そこへ書き込むからです。src は読むだけなので const を付けます。引数の型を見るだけで、どちらが写す先かが分かるようになっています。

    写った先は独立している

    コピーが本物のコピーなら、片方をいじってももう片方は変わらないはずです。逆に言えば、写した先を書き換えて元が変わってしまったら、それは写せていなかったという証拠になります。今回の課題では、コピーしたあとに1文字だけ書き換えて、元が無事かどうかを目で確かめます。

    写す先は自分で用意する

    my_strcpy は写す先の領域を作りません。すでにある器へ運ぶだけです。ですから呼ぶ側が、写すものが収まる広さの器を先に用意しておく必要があります。前回の話をここで使うと、必要なのは strlen(src) + 1 バイトです。終端のぶんを足すのを忘れると、文字は全部入るのに終わりの印だけがはみ出します。

    なお、strcpy は写す先の広さを一切見ません。dest が足りなくても、src の終端まで書き続けます。関数の側からは器の広さを知りようがないからです。ポインタは先頭の番地しか持っておらず、そこから何バイト使ってよいかという情報はどこにも付いていません。この「広さを知らないまま書き込む」という性質が、次回のバッファオーバーフローの正体です。まずは仕組みを手で書いてみましょう。

    要件

    1. my_strcpy という関数を自分で書く。第1引数が写す先、第2引数が写す元
    2. 写し終わったあとに終端のヌル文字を必ず置く
    3. 1行目に コピー Tanaka の形で写した結果を表示する
    4. 2行目に 書き換え Xanaka の形で、写した側の先頭を 'X' にした結果を表示する
    5. 3行目に 元 Tanaka の形で元の名前を表示する

    ヒント

    while の条件は写す元を見ます。抜けたあとに写す先へ '\0' を置いてください

    書き換えは copy[0] = 'X'; で構いません

    strcpy をそのまま呼ばず、自分の関数を使ってください

    生田 陸人
    監修生田 陸人
    ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
    編集 ゆめさく編集部·公開 2026/08/07

    関連レッスン

    • バッファオーバーフロー体験

      あふれがなぜ危険かを説明し、安全な書き方に直せるようになります。

    • 文字列を分解する

      区切り文字で分ける処理を書けるようになります。

    • 動的な文字列

      長さに合わせて必要なぶんだけ確保できるようになります。

    • つくる 名前入力の安全化

      入力処理を、あふれない形に全面的に書き直せるようになります。

    このレッスンに出てくる用語

    意味があいまいなまま進んだ語は、ここから読み直せます。

    • 配列サイズ固定の同型データの集まり
    • 引数位置引数=順番で渡す。
    • 関数処理に名前を付けて再利用できる単位
    main.c
    エディタを読み込んでいます

    メモ

    strcpyを自作する

    ⌘S で保存