English

ポインタ(Pointers)

Cm言語のポインタは、C/C++互換のメモリアドレス操作を提供します。

📋 目次

基本的な使い方

ポインタ宣言

// 基本的なポインタ宣言
int* p;

// 複数のポインタ
int* a, *b, *c;

// ポインタのポインタ
int** pp;

struct Point { int x; int y; }

// 構造体ポインタ
Point* ptr;

アドレス演算子

&演算子で変数のアドレスを取得します。

struct Point { int x; int y; }

int main() {
    int x = 42;
    int* p = &x;  // xのアドレス

    Point pt = Point(10, 20);
    Point* ptr = &pt;  // ptのアドレス
    return 0;
}

デリファレンス

*演算子でポインタの参照先にアクセスします。

int main() {
    int x = 10;
    int* p = &x;

    // 読み取り
    int value = *p;  // 10

    // 書き込み
    *p = 20;
    // xは20になる
    return 0;
}

ポインタと借用(v0.11.0以降)

Cm v0.11.0では、ポインタが借用システムの基盤となっています:

int main() {
    // constポインタによる不変借用
    const int value = 42;
    const int* immutable_ref = &value;
    println("借用した値: {*immutable_ref}");
    // *immutable_ref = 50;  // エラー: 変更不可

    // ポインタによる可変借用
    int mut_value = 100;
    int* mutable_ref = &mut_value;
    *mutable_ref = 200;  // OK: 変更可能
    println("変更後: {mut_value}");  // 200

    // 借用中は移動不可
    int data = 10;
    int* borrowed = &data;
    // int moved = move data;  // エラー: 借用中の値は移動できない

    return 0;
}

重要なポイント:

ポインタ演算

int main() {
    int[5] arr = [1, 2, 3, 4, 5];
    int* p = arr;  // 配列の先頭アドレス

    // ポインタの加算
    int first = *p;      // 1
    int second = *(p + 1);  // 2
    int third = *(p + 2);   // 3

    // ポインタのインクリメント
    p++;
    int value = *p;  // 2

    // ポインタループ
    int* end = arr + 5;
    for (int* iter = arr; iter != end; iter++) {
        println("{}", *iter);
    }
    return 0;
}

構造体ポインタ

基本的なアクセス

struct Point {
    int x;
    int y;
}

int main() {
    Point pt = Point(10, 20);
    Point* ptr = &pt;

    // Cmでは . 演算子で構造体ポインタのフィールドにアクセス
    // (-> 演算子ではなく . 演算子を使用)
    (*ptr).x = 30;
    (*ptr).y = 40;
    return 0;
}

ポインタ経由の関数呼び出し

interface Printable {
    void print();
}

struct Point { int x; int y; }

impl Point for Printable {
    void print() {
        println("({}, {})", self.x, self.y);
    }
}

int main() {
    Point pt = Point(5, 10);
    Point* ptr = &pt;
    
    (*ptr).print();  // "(5, 10)"
    return 0;
}

配列とポインタ

Array Decay

配列は自動的にポインタに変換されます。

int main() {
    int[5] arr = [1, 2, 3, 4, 5];

    // 暗黙的変換
    int* p = arr;  // arr[0]のアドレス
    return 0;
}

// 関数に渡す
void process(int* data, int size) {
    for (int i = 0; i < size; i++) {
        data[i] *= 2;
    }
}

int main() {
    int[5] arr = [1, 2, 3, 4, 5];
    process(arr, 5);  // 配列→ポインタ変換
    return 0;
}

ポインタと配列の等価性

int main() {
    int[5] arr = {10, 20, 30, 40, 50};
    int* p = arr;

    // 以下は全て同じ
    int v1 = arr[2];   // 30
    int v2 = p[2];     // 30
    int v3 = *(p + 2); // 30
    int v4 = *(arr + 2);  // 30
    return 0;
}

関数ポインタ

関数ポインタ宣言

// 関数ポインタ型: 戻り値型*(引数型...)
int*(int, int) op;

int add(int a, int b) {
    return a + b;
}

int multiply(int a, int b) {
    return a * b;
}

int main() {
    // 関数ポインタに代入
    op = add;
    int result1 = op(10, 20);  // 30
    
    op = multiply;
    int result2 = op(10, 20);  // 200
    
    return 0;
}

高階関数

// 関数ポインタを引数に取る関数
int apply(int*(int, int) fn, int x, int y) {
    return fn(x, y);
}

int max(int a, int b) {
    return a > b ? a : b;
}

int min(int a, int b) {
    return a < b ? a : b;
}

int main() {
    int result1 = apply(max, 10, 5);  // 10
    int result2 = apply(min, 10, 5);  // 5
    return 0;
}

Null ポインタ

int main() {
    // Nullポインタ
    int* p = null;

    // Nullチェック
    if (p == null) {
        println("Pointer is null");
    }

    // Nullポインタのデリファレンスは未定義動作
    // *p = 10;  // 危険!
    return 0;
}

typedef型ポインタ

typedef MyInt = int;
typedef MyFloat = float;

// typedef型のポインタ
MyInt* p1;
MyFloat* p2;

int main() {
    MyInt x = 42;
    p1 = &x;
    return 0;
}

// インタプリタおよびLLVMで動作

実装状況

機能 JIT LLVM WASM JS
基本的なポインタ
デリファレンス
ポインタ演算
構造体ポインタ
配列→ポインタ
関数ポインタ
typedef型ポインタ ⚠️

サンプルコード

完全なサンプルは以下を参照してください:

関連ドキュメント


更新日: 2026-02-10