【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)); // 解放しないためリーク
}
適切に管理しないと、長時間のプログラム実行でメモリ不足を引き起こします。