【C言語】ポインタとメモリ管理に関するキーワードと使い方

【C言語】ポインタとメモリ管理に関するキーワードと使い方

ポインタとは

ポインタはメモリ上のアドレスを格納する変数です。通常の変数は値を直接保持しますが、ポインタはその値が格納されているメモリのアドレスを指します。


int a = 10;
int *p = &a;  // pはaのアドレスを保持
printf("%d\n", *p);  // aの値(10)を出力

メモリ管理の基本

C言語では、メモリは主に以下の4つの領域に分類されます:

  • 静的領域(静的変数やグローバル変数が格納される)
  • スタック領域(ローカル変数や関数呼び出し時のデータが格納される)
  • ヒープ領域(動的メモリ割り当てに使用される)
  • コード領域(プログラムの命令が格納される)

動的メモリ割り当て

動的メモリ割り当ては、プログラム実行中に必要なメモリを確保する手法です。malloc()を使うことで、指定したバイト数のメモリをヒープ領域に確保できます。


int *p = (int*)malloc(sizeof(int));  // int型のメモリを確保
if (p != NULL) {
    *p = 100;
    printf("%d\n", *p);  // 100を出力
}
free(p);  // メモリ解放

メモリ解放と注意点

確保したメモリは不要になったらfree()で解放する必要があります。解放しないとメモリリークが発生します。


int *p = (int*)malloc(sizeof(int));
free(p);  // メモリ解放
p = NULL;  // ダングリングポインタを防ぐ

ポインタと配列

配列の名前はポインタのように振る舞います。


int arr[] = {1, 2, 3};
int *p = arr;
printf("%d\n", *(p + 1));  // 2を出力

ポインタのポインタ

ポインタを指すポインタも作成できます。


int a = 10;
int *p = &a;
int **pp = &p;
printf("%d\n", **pp);  // 10を出力

関数ポインタ

関数のアドレスを保持し、呼び出すことができます。


#include <stdio.h>

void hello() {
    printf("Hello, World!\n");
}

int main() {
    void (*func_ptr)() = hello;
    func_ptr();  // Hello, World!を出力
    return 0;
}

構造体ポインタ

構造体のメンバにポインタ経由でアクセスできます。


struct Point {
    int x, y;
};

struct Point p = {10, 20};
struct Point *ptr = &p;
printf("%d, %d\n", ptr->x, ptr->y);  // 10, 20を出力

ダングリングポインタ

解放済みのメモリを指すポインタは、ダングリングポインタと呼ばれます。


int *p = (int*)malloc(sizeof(int));
free(p);
printf("%d\n", *p);  // 未定義動作(危険)

メモリリーク

確保したメモリを適切に解放しないと、メモリリークが発生します。


void leak() {
    int *p = (int*)malloc(sizeof(int));  // 解放しないためリーク
}

適切に管理しないと、長時間のプログラム実行でメモリ不足を引き起こします。

コメントは受け付けていません。