スタック初期化
CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 14/61。
すべてのオブジェクトをヒープ上に置く必要はありません。構造体が小さく、寿命が短い場合は、スタック上に割り当てるほうが簡単で高速です。mallocもfreeも必要なく、メモリリークのリスクもありません。
ポインタを返す代わりに、factory function は struct を値渡しで返すことができます。struct 全体が呼び出し元にコピーされます。
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p;
p.x = x;
p.y = y;
return p;
}
呼び出し元は完全に初期化されたコピーを受け取ります。
Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);
ポインターはなく、クリーンアップも必要ありません。originとcursorがスコープ外になると、自動的に破棄されます。
このアプローチは、動的に割り当てられたメンバーを持たない小さな構造体に最適です。より大きなオブジェクトやヒープメモリへのポインターを含むオブジェクトの場合は、mallocを使うコンストラクタパターンのほうが依然として適しています。
チャレンジ
簡単Temperature モジュールを作成し、ファクトリ関数を使ってスタック上に温度の読み取り値を生成しましょう。前のレッスンで扱ったヒープベースのコンストラクターとは異なり、この方法では構造体を値として返します。malloc も free も必要なく、シンプルで効率的なスタック割り当てを行えます。
3つのファイルを作成します。
temperature.h:2つのメンバー、double celsiusとchar scale(Celsius を表す 'C' を格納するため)を持つTemperature構造体を宣言します。また、2つの関数も宣言します。create_temperature:double 値を受け取り、Temperature構造体を値として返します(ポインターではありません!)。temperature_to_fahrenheit:const Temperature *を受け取り、対応する Fahrenheit の温度を double として返します。
TEMPERATURE_Hを使ってインクルードガードを設定します。temperature.c:両方の関数を実装します。ファクトリ関数ではローカルTemperature変数を作成し、そのフィールドを初期化し(scaleを'C'に設定します)、それを返します。変換式は次のとおりです:fahrenheit = celsius * 9.0 / 5.0 + 32.0main.c:ファクトリ関数を使って温度の読み取り値を作成し、Celsius と Fahrenheit の値を両方表示します。
入力として1つの値、つまり Celsius の温度(double)を受け取ります。
main ファイルでは、create_temperature を使って、指定された値で Temperature 構造体を作成します。その後、元の Celsius 値と、それに対応する Fahrenheit の値を出力します。
次の形式で出力します。
Celsius: {celsius}
Fahrenheit: {fahrenheit}両方の値に %.2f を使用し、小数点以下2桁まで表示してください。
たとえば、入力が 25.0 の場合、出力は次のようになります。
Celsius: 25.00
Fahrenheit: 77.00この方法がいかにすっきりしているかに注目してください。メモリ管理を気にすることなく、完全に初期化された構造体を受け取れます。Temperature 変数がスコープ外に出ると、自動的にクリーンアップされます。
自分で試してみよう
#include <stdio.h>
#include "temperature.h"
int main() {
double celsius_input;
scanf("%lf", &celsius_input);
// TODO: create_temperature を使って Temperature 構造体を作成する
// TODO: %.2f 形式で摂氏の値を出力する
// TODO: temperature_to_fahrenheit を使って変換し、華氏の値を出力する
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Cオンラインコンパイラ