Menu
Coddy logo textTech

スタック初期化

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

すべてのオブジェクトがヒープ上に存在する必要はありません。構造体が小さく、寿命が短い場合、スタック上に割り当てる方が簡単で高速です。mallocfree も不要で、メモリリークのリスクもありません。

ポインタを返す代わりに、ファクトリ関数は構造体を値渡しで返すことができます。構造体全体が呼び出し元にコピーされます:

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);

ポインタはなく、クリーンアップも不要です。origincursor がスコープ外になると、それらは自動的に破棄されます。

このアプローチは、動的に割り当てられたメンバを持たない小さな構造体に最適です。より大きなオブジェクトや、ヒープメモリへのポインタを含むものに対しては、malloc を使用したコンストラクタパターンが引き続きより良い選択肢となります。

challenge icon

チャレンジ

簡単

ファクトリ関数を使用してスタック上に温度の測定値を作成する Temperature モジュールを構築しましょう。以前のレッスンのヒープベースのコンストラクタとは異なり、このアプローチでは構造体を値で返します。mallocfree も不要で、シンプルかつ効率的なスタック割り当てのみを使用します。

3つのファイルを作成します:

  • temperature.h: 2つのメンバを持つ Temperature 構造体を宣言します:double celsiuschar scale (摂氏を表す 'C' を格納するため)。また、2つの関数を宣言します:
    • create_temperature — double 値を受け取り、Temperature 構造体を値で返します(ポインタではありません!)。
    • temperature_to_fahrenheitconst Temperature * を受け取り、対応する華氏の温度を double として返します。
    インクルードガードにはシンボル TEMPERATURE_H を使用してください。
  • temperature.c: 両方の関数を実装します。ファクトリ関数は、ローカルの Temperature 変数を作成し、そのフィールドを初期化し(scale'C' に設定)、それを返す必要があります。変換式は fahrenheit = celsius * 9.0 / 5.0 + 32.0 です。
  • main.c: ファクトリ関数を使用して温度の測定値を作成し、摂氏と華氏の両方の値を表示します。

1つの入力を受け取ります:摂氏の温度(double 型)。

メインファイルで、create_temperature を使用して、与えられた値を持つ Temperature 構造体を作成します。次に、元の摂氏の値とその華氏の換算値を表示します。

出力は次の形式で表示してください:

Celsius: {celsius}
Fahrenheit: {fahrenheit}

両方の値に %.2f を使用して、小数点以下2桁まで表示してください。

例えば、入力が 25.0 の場合、出力は次のようになります:

Celsius: 25.00
Fahrenheit: 77.00

このアプローチがいかにクリーンであるかに注目してください。メモリ管理の心配をすることなく、完全に初期化された構造体を受け取ることができます。Temperature 変数がスコープ外になると、自動的にクリーンアップされます。

チートシート

ファクトリ関数は、ポインタではなく値渡しで構造体を返すことができます。これにより、構造体はスタック上に割り当てられます。mallocfree も不要で、メモリリークも発生しません。

値渡しで返すファクトリ関数の例:

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);

構造体は呼び出し元にコピーされ、スコープを抜けると自動的に破棄されます。この手法は、動的に割り当てられたメンバを持たない小さな構造体に最適です。

自分で試してみよう

#include <stdio.h>
#include "temperature.h"

int main() {
    double celsius_input;
    scanf("%lf", &celsius_input);
    
    // TODO: create_temperature を使用して Temperature 構造体を作成する
    
    // TODO: %.2f フォーマットを使用して摂氏(Celsius)の値を出力する
    
    // TODO: temperature_to_fahrenheit を使用して華氏(Fahrenheit)の値に変換し、出力する
    
    return 0;
}
quiz icon腕試し

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

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