コース一覧
    C言語中級 文字列・構造体
    構造体の動的確保

    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分

    構造体の動的確保

    学生の人数を、書いた時点で決めたくない

    前回まで Student はローカル変数として置いていました。ローカル変数はその関数を抜けた瞬間に消えるので、「学生を 1 人つくって返す関数」を素直に書くと壊れます。

    c

    Student *create_bad(void) {
        Student s;          /* 関数の中だけで生きる */
        s.score = 80;
        return &s;          /* 抜けた瞬間に消えるものの番地を返している */
    }

    これは第 2 章で見たダングリングポインタです。返ってきた番地は、もう誰のものでもありません。中身を読めることもありますが、それはたまたま上書きされていないだけです。

    malloc(sizeof(Student)) で構造体 1 つ分を借りる

    ヒープから借りた領域は、free するまで生き続けます。誰の関数が終わろうと関係ありません。だから「つくって返す」にはヒープを使います。

    c

    Student *s = malloc(sizeof(Student));

    sizeof(Student) は構造体 1 つ分のバイト数です。ここで sizeof(Student *) と書き間違えるのが定番の事故で、そう書くとポインタ 1 個分しか借りられません。構造体はそれより大きいので、s->name に名前を書いた時点で借りていない場所を壊します。コンパイラは通してしまうので、自分で気づくしかありません。

    書き間違えを防ぐ書き方として、型ではなく変数から大きさを取る形があります。

    c

    Student *s = malloc(sizeof(*s));

    *s は「s が指す先」つまり Student なので、意味は同じです。型名を二度書かないぶん、あとで型を変えてもずれません。

    確保に失敗したら NULL が返る

    malloc は借りられなかったとき NULL を返します。返ってきたポインタをそのまま -> で触ると、そこで落ちます。使う前に必ず確かめてください。

    c

    if (s == NULL) {
        printf("確保できませんでした\n");
        return 1;
    }

    借りたものには持ち主がいる

    create_student の中で malloc して返す、という形にすると、確保した場所と解放する場所が別の関数になります。ここで大事なのは「返してもらった側が持ち主になり、free する責任も引き受ける」という約束をはっきりさせることです。C にはこれを強制する仕組みが無いので、関数の名前とコメントで示すしかありません。create_ で始まる名前なら呼び出し側が捨てる、という慣習はよく使われます。

    解放したあとにポインタへ NULL を入れておくと、うっかり使ったときに「番地はあるが中身は他人のもの」ではなく、はっきり落ちるか、NULL 判定で弾けます。

    c

    free(s);
    s = NULL;

    要件

    1. create_student は malloc で Student 1つ分を確保する
    2. 確保に失敗したら NULL を返す
    3. 名前は strcpy でコピーし、点数は代入する
    4. 表示のあとに free し、ポインタに NULL を入れる

    ヒント

    確保する大きさは sizeof(Student) です。sizeof(Student *) ではポインタ1個分しかありません

    free したあとに s = NULL; を書くと、最後の1行が NULL と出ます

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

    関連レッスン

    • 動的な構造体配列

      構造体の一覧を動的な配列で持てるようになります。

    • 関数ポインタ

      関数そのものを引数として渡せるようになります。

    • qsortで並べ替える

      比較関数を書いて qsort で並べ替えられるようになります。

    • つくる 動的Student完成

      構造体と動的メモリで成績管理を作り直せるようになります。

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

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

    • 変数データに名前をつけて参照する仕組み
    • 関数処理に名前を付けて再利用できる単位
    • ヒープ親が子より常に大きい(最大ヒープ)または小さい(最小ヒープ)木構造。
    • コメント# で1行コメント。
    main.c
    エディタを読み込んでいます

    メモ

    構造体の動的確保

    ⌘S で保存