static関数
CoddyのCジャーニー「Object Oriented Programming」セクションの一部 — レッスン 4/61。
コードを複数のファイルに分割すると、ソースファイルで定義されたすべての関数は、デフォルトで他のファイルから参照可能になります。しかし、内部でのみ使用されるべきヘルパー関数、つまり他のファイルがアクセスしたり、その存在を知る必要さえない関数が必要になることがあります。
static キーワードを関数に適用すると、その可視性は定義されたファイル内に制限されます。これにより、たとえ他のファイルで宣言を試みたとしても、他のソースファイルからは呼び出すことができないプライベートな関数が作成されます。
// math_utils.c
#include "math_utils.h"
// プライベートヘルパー - このファイル内でのみ参照可能
static int square(int x) {
return x * x;
}
// 公開関数 - main.cから呼び出し可能
int sum_of_squares(int a, int b) {
return square(a) + square(b);
}
この例では、sum_of_squares はヘッダーで宣言されており、どこでも使用できます。しかし、square には static が指定されているため、math_utils.c 内にのみ存在します。もし main.c が square() を直接呼び出そうとすると、リンカーはエラーを生成します。その関数は単にファイルの外部には存在しないからです。
これは、ファイルレベルでカプセル化を実現するためのC言語の手法です。static関数を使用すると、実装の詳細を隠蔽することができ、内部で必要なヘルパーロジックを使用しながら、パブリックインターフェースをクリーンに保つことができます。
チャレンジ
簡単数値の 2 乗を計算するためのプライベートなヘルパー関数を使用する距離計算機を作成しましょう。この詳細は、プログラムの他の部分からは隠されている必要があります。
3 つのファイルを作成します:
distance.h: 2 つの点を表す 4 つの整数 (x1, y1, x2, y2) を受け取り、整数を返す単一のパブリック関数distance_squaredを宣言するヘッダーファイルです。シンボルDISTANCE_Hを使用してインクルードガードを含めてください。distance.c: 実装を含むソースファイルです。整数を受け取り、その 2 乗を返すstaticなヘルパー関数squareを作成します。このヘルパーはdistance.c内でのみ参照可能である必要があります。次に、このスタティックヘルパーを使用して (x2-x1)² + (y2-y1)² を計算するdistance_squaredを実装します。main.c: ヘッダーをインクルードし、パブリック関数を使用するメインファイルです。ここではsquareヘルパーにはアクセスできず、distance_squaredのみが利用可能である必要があります。
distance_squared 関数は、2 点間のユークリッド距離の 2 乗を計算します。square 関数を static に保つことで、この実装の詳細を distance.c 以外のコードから隠蔽します。
4 つの整数入力 x1、y1、x2、および y2 を受け取ります。
次の形式で 2 乗距離を出力してください:
Squared distance: {result}例えば、点 (0, 0) と (3, 4) の場合、出力は次のようになります:
Squared distance: 25チートシート
staticキーワードは、関数の可視性をその関数が定義されているファイル内に制限し、他のソースファイルから呼び出すことができないプライベートな関数を作成します。
// プライベートなヘルパー関数 - このファイル内でのみ可視
static int square(int x) {
return x * x;
}
// 公開関数 - 他のファイルから呼び出し可能
int sum_of_squares(int a, int b) {
return square(a) + square(b);
}
静的関数はファイルレベルのカプセル化を提供し、公開インターフェースをクリーンに保ちながら、実装の詳細を隠蔽することができます。
自分で試してみよう
#include <stdio.h>
#include "distance.h"
int main() {
int x1, y1, x2, y2;
scanf("%d", &x1);
scanf("%d", &y1);
scanf("%d", &x2);
scanf("%d", &y2);
// TODO: 入力された座標を使用して distance_squared を呼び出す
// そして、結果を "Squared distance: {result}" という形式で出力する
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。