歴史的に、モジュラリティは大規模なプロジェクトを独立した論理的な部分に分割する方法として登場し、可読性の向上、コードの再利用、開発者間の責任の分担を図ります。Cにおけるモジュラリティはファイルレベル、すなわちソースファイル (.c) とヘッダーファイル (.h) で実現されます。
プログラマーが直面する問題は、コードの各部分間の相互作用をどのように構成し、定義の重複を避け、カプセル化を乱さず、ビルドを簡単にするかです。
解決策は、インターフェースと実装の分離を使用することです:
モジュラコードの構造の例:
// mymath.h #ifndef MYMATH_H #define MYMATH_H int add(int, int); #endif // mymath.c #include "mymath.h" int add(int a, int b) { return a + b; } // main.c #include "mymath.h" #include <stdio.h> int main() { printf("%d ", add(3, 4)); return 0; }
主な特徴:
ヘッダーファイルに extern で変数を定義し、複数のモジュールで安全に使用できますか?
いいえ!グローバル変数は必ず一つの .c ファイルで定義し、ヘッダファイルでは extern で宣言する必要があります。さもなければ、「multiple definition」によるリンキングエラーが発生します。
各ヘッダファイルを #include で一度だけ含める必要がありますか?
各 .h ファイルをガードマクロ (#ifndef/#define/#endif) で囲む必要があります。そうしないと、複数回のインクルードによる宣言の衝突とコンパイルエラーが発生します。
Cでプライベートデータ構造のクリーンなカプセル化(オペークポインタ)を実現できますか?
はい。「オペークポインタ」は、構造の詳細をユーザーから隠すことができます:
// mystruct.h typedef struct MyStruct MyStruct; MyStruct* create(void); void destroy(MyStruct*); // mystruct.c struct MyStruct { int a; };
すべてのロジックが一つの長い .c ファイルに実装され、コードが繰り返され、グローバル変数が衝突し、リンキングエラーが発生します。
メリット:
デメリット:
コードはモジュールに分解され、インクルードガードが使用され、プライベートデータはオペークポインタで保護されます。
メリット:
デメリット: