voidポインタの復習
CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 49/61。
void* は C で「何かへのポインターだが、それが何かは伝えない」と表現する方法です。int、float、構造体など、あらゆる data type のアドレスを保持できます。このため、C で汎用的なコードを書くための基盤となります。
注意点は、void* を直接デリファレンスできないことです。コンパイラーには、何バイトを読み取ればよいのか、またそれらをどのように解釈すればよいのかが分かりません。data を使用するには、正しい type にキャストし直す必要があります。
void print_int(void* data) {
int* p = (int*)data;
printf("%d\n", *p);
}
int main() {
int x = 42;
print_int(&x);
return 0;
}この柔軟性には責任が伴います。間違った type にキャストしても、コンパイラーは止めてくれませんが、プログラムはでたらめな結果を出したり、クラッシュしたりします。そのため、汎用的な function では、void* と type の指示子(enum や flag など)を組み合わせることがよくあります。これにより、function は data を正しく解釈する方法を把握できます。
これからのレッスンでは、void* を使ってあらゆる type の data を格納できるコンテナを構築し、真に再利用可能なデータ構造を実現します。
チャレンジ
簡単print_valueという名前のfunctionを作成してください。このfunctionは2つのパラメーターを受け取ります。dataへのvoid* pointerと、int type flagです。functionは、type flagに基づいてdataを解釈し、出力する必要があります。
- type flagが
0の場合、pointerをint*にキャストし、整数値を出力する - type flagが
1の場合、pointerをfloat*にキャストし、小数点以下2桁でfloat値を出力する
プログラムは2つの入力を受け取ります。
- type flag(整数の場合は
0、floatの場合は1) - 数値
type flagに基づいて、値を適切な変数の型で格納し、その変数へのpointerとtype flagを指定してprint_valueを呼び出してください。
入力が0と42の場合の出力例:
42入力が1と3.14の場合の出力例:
3.14入力が0と-17の場合の出力例:
-17入力が1と99.5の場合の出力例:
99.50自分で試してみよう
#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;
}このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Cオンラインコンパイラ