C言語-3

ポインタ、配列、関数の基礎を理解したところで、C言語の効率と制御の核心に迫る「動的メモリ管理」と、データ構造の基本となる「構造体」について解説します。


4. 動的メモリ管理(Dynamic Memory Allocation)

配列は宣言時にサイズが固定されてしまいますが、プログラムの実行中に必要なサイズだけメモリを確保し、不要になったら解放する仕組みが動的メモリ管理です。これにより、効率的なメモリ利用が可能になります。

⚙️ 重要な関数 (stdlib.h)

動的メモリ管理には、標準ライブラリ stdlib.h の以下の3つの関数を使用します。

関数目的戻り値
malloc指定したバイトサイズのメモリを確保する。確保されたメモリの先頭アドレス(void*型)。
callocmallocと同様だが、確保したメモリをすべてゼロで初期化する。確保されたメモリの先頭アドレス(void*型)。
free確保したメモリを解放し、OSに返却する。なし(void)。

Google スプレッドシートにエクスポート

📝 malloc の利用例

mallocは、必要なバイト数を計算し、その結果をポインタに格納します。

C

#include <stdio.h>
#include <stdlib.h> // malloc, free を使うために必要

int main() {
    // int型を5つ格納するためのメモリサイズを計算
    // sizeof(int) * 5 = 20バイト (一般的な環境)
    int *ptr = (int*)malloc(sizeof(int) * 5); 

    if (ptr == NULL) {
        printf("メモリ確保に失敗しました。\n");
        return 1;
    }

    // 確保したメモリを配列のように使用
    for (int i = 0; i < 5; i++) {
        ptr[i] = i * 10;
        printf("ptr[%d] = %d\n", i, ptr[i]);
    }
    
    // --- 処理終了後、必ずメモリを解放する ---
    free(ptr);
    ptr = NULL; // 解放後はポインタをNULLにしておくと安全性が高まる

    return 0;
}

🚨 メモリリーク(Memory Leak)

mallocなどで確保したメモリを**freeし忘れると、そのメモリ領域はプログラム終了まで使われず残り続けてしまいます。これがメモリリーク**です。C言語のプログラミングでは、メモリ確保と解放のペアを厳密に管理することが極めて重要です。


5. 構造体(Structures)

C言語では、異なるデータ型(intchar[]floatなど)をひとつのまとまりとして扱うために構造体を使用します。これは、C#におけるクラスレコードのようなデータオブジェクトの基本形です。

🧱 構造体の定義

struct キーワードを使って定義します。

C

// Studentという名前の構造体を定義
struct Student {
    int id;               // 学生番号(整数)
    char name[20];        // 名前(文字配列)
    float score;          // 点数(浮動小数点数)
};

// structを省略できるように、typedefを使うのが一般的
typedef struct {
    int id;
    char name[20];
    float score;
} Employee; // 今後は Employee だけで使える

📝 構造体メンバーへのアクセス

構造体の変数(インスタンス)を宣言し、その中の個々のデータ(メンバー)にアクセスするには**ドット演算子 (.)**を使用します。

C

// Student型の変数を宣言し、初期化
struct Student s1 = {101, "Alice", 85.5f};

// ドット演算子を使ってメンバーにアクセス
printf("名前: %s, 点数: %.1f\n", s1.name, s1.score); // 出力: 名前: Alice, 点数: 85.5

// メンバーの値を変更
s1.score = 90.0f;

➡️ 構造体ポインタとアロー演算子

構造体をポインタ経由で扱う場合、メンバーへのアクセスには**アロー演算子 (->)**を使用します。

C

struct Student s2 = {202, "Bob", 78.0f};

// s2を指すポインタを宣言
struct Student *ptr_s2 = &s2;

// アロー演算子 (->) を使ってメンバーにアクセス
printf("ID: %d\n", ptr_s2->id); // s2.id にアクセスするのと同じ

// アロー演算子は、以下の式を短縮したものです
// (*ptr_s2).id 

C言語では、大きな構造体を関数に渡す際、コピーを防いで処理を効率化するためにポインタ渡し(アロー演算子を使用)が頻繁に行われます。

これで、C言語の基本的な概念は一通り網羅できました。これらの知識があれば、C言語の応用分野であるデータ構造、ファイルI/O、システムプログラミングへと進むことができます。