Menu
Coddy logo textTech

voidポインタの復習

CoddyのCジャーニー「Object Oriented Programming」セクションの一部 — レッスン 49/61。

void* は、「何らかのデータへのポインタですが、それが何であるかは教えません」というC言語流の表現です。これは、intfloatstruct、あるいはその他のあらゆるデータ型の型のアドレスを保持できます。これにより、C言語で汎用的なコードを記述するための基礎となります。

注意点は、void* を直接デリファレンス(間接参照)できないことです。コンパイラは、何バイト読み取るべきか、あるいはそれらをどのように解釈すべきかを知りません。データを使用するには、正しい型にキャストし直す必要があります:

void print_int(void* data) {
    int* p = (int*)data;
    printf("%d\n", *p);
}

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

この柔軟性には責任が伴います。誤った型にキャストしても、コンパイラはそれを止めませんが、プログラムはゴミデータを出力したりクラッシュしたりします。そのため、汎用関数では void* と型識別子(enumやフラグなど)をペアにすることが多く、それによって関数がデータを正しく解釈する方法を判断できるようにします。

今後のレッスンでは、void* を使用して、あらゆる型のデータを格納できるコンテナを構築し、真に再利用可能なデータ構造を実現します。

challenge icon

チャレンジ

簡単

データへの void* ポインタと int 型のフラグの2つのパラメータを受け取る print_value という関数を作成してください。この関数は、型フラグに基づいてデータを解釈し、出力する必要があります。

  • 型フラグが 0 の場合、ポインタを int* にキャストし、整数値を出力します。
  • 型フラグが 1 の場合、ポインタを float* にキャストし、小数点以下2桁で浮動小数点数を出力します。

プログラムは2つの入力を受け取ります:

  1. 型フラグ(整数の場合は 0、浮動小数点数の場合は 1
  2. 数値

型フラグに基づいて、適切な変数型に値を格納し、その変数へのポインタと型フラグを引数にして print_value を呼び出してください。

入力が 042 の場合の出力例:

42

入力が 13.14 の場合の出力例:

3.14

入力が 0-17 の場合の出力例:

-17

入力が 199.5 の場合の出力例:

99.50

チートシート

void* は、あらゆるデータ型のアドレスを保持できる汎用ポインタです。C言語で汎用的なコードを記述するための柔軟性を提供します。

void* を直接デリファレンスすることはできません。まず正しい型にキャストする必要があります。

void print_int(void* data) {
    int* p = (int*)data;
    printf("%d\n", *p);
}

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

汎用関数は、データを正しく解釈する方法を知るために、void* を型インジケータ(enumやフラグなど)とペアにすることがよくあります。誤った型にキャストすると、未定義の動作やクラッシュの原因となる可能性があります。

自分で試してみよう

#include <stdio.h>

// TODO: ここに print_value 関数を記述してください


int main() {
    int type_flag;
    scanf("%d", &type_flag);
    
    if (type_flag == 0) {
        int int_value;
        scanf("%d", &int_value);
        
        // TODO: int_value へのポインタと type_flag を引数に指定して print_value を呼び出してください
        
    } else if (type_flag == 1) {
        float float_value;
        scanf("%f", &float_value);
        
        // TODO: float_value へのポインタと type_flag を引数に指定して print_value を呼び出してください
        
    }
    
    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

Object Oriented Programmingのすべてのレッスン