C言語におけるモジュール結合度

C言語におけるモジュール結合度を弱いものから強いものまで、コード例を交えて説明します。

## 1. データ結合（最も弱い結合）
データ結合は、モジュール間で単純なデータ（基本型）のみをパラメータとして渡す方法です。
```c
// モジュールA
int calculate_area(int width, int height) {
    return width * height;
}

// モジュールB
void main() {
    int w = 5;
    int h = 10;
    int area = calculate_area(w, h);
    printf("Area: %d\n", area);
}
```
この例では、単純な整数値のみを引数として渡しており、モジュール間の依存関係が最小限です。

## 2. スタンプ結合
スタンプ結合は、構造体などの複合データ型を介して通信する方式です。
```c
// 共有構造体
typedef struct {
    char name[50];
    int age;
    float salary;
} Employee;

// モジュールA
void print_employee_details(Employee emp) {
    printf("Name: %s, Age: %d, Salary: %.2f\n", emp.name, emp.age, emp.salary);
}

// モジュールB
void main() {
    Employee emp = {"John Doe", 30, 50000.0};
    print_employee_details(emp);
}
```
この例では、`Employee`構造体を通じてデータを共有していますが、モジュールAは構造体のフィールドにのみアクセスし、変更はしていません。

## 3. 制御結合
制御結合は、あるモジュールが他のモジュールの内部ロジックに影響を与える場合に発生します。

```c
// モジュールA
void process_data(int data[], int size, int mode) {
    if (mode == 0) {
        // 合計を計算
        int sum = 0;
        for (int i = 0; i < size; i++) {
            sum += data[i];
        }
        printf("Sum: %d\n", sum);
    } else if (mode == 1) {
        // 平均を計算
        int sum = 0;
        for (int i = 0; i < size; i++) {
            sum += data[i];
        }
        printf("Average: %.2f\n", (float)sum / size);
    }
}

// モジュールB
void main() {
    int data[] = {1, 2, 3, 4, 5};
    process_data(data, 5, 0); // 合計モード
    process_data(data, 5, 1); // 平均モード
}
```
この例では、モジュールBがモードフラグを通じてモジュールAの動作を制御しています。これにより、モジュール間の結合度が高まります。

## 4. 外部結合
外部結合は、複数のモジュールが同じグローバルデータを参照・変更する場合に発生します。
```c
// グローバル変数
int g_counter = 0;

// モジュールA
void increment_counter() {
    g_counter++;
    printf("Counter incremented to: %d\n", g_counter);
}

// モジュールB
void reset_counter() {
    g_counter = 0;
    printf("Counter reset to: %d\n", g_counter);
}

// モジュールC
void main() {
    increment_counter();
    increment_counter();
    reset_counter();
    increment_counter();
}
```
この例では、複数のモジュールがグローバル変数g_counterにアクセスして変更しています。

## 5. 共通結合
共通結合は、複数のモジュールが共有メモリ領域にアクセスする場合に発生します。

```c
// 共有メモリ領域
typedef struct {
    int status;
    char message[100];
    float values[10];
} SharedData;

SharedData shared_memory;

// モジュールA
void update_status(int new_status) {
    shared_memory.status = new_status;
}

// モジュールB
void update_message(const char* new_message) {
    strcpy(shared_memory.message, new_message);
}

// モジュールC
void update_values(float new_values[], int size) {
    for (int i = 0; i < size && i < 10; i++) {
        shared_memory.values[i] = new_values[i];
    }
}

// モジュールD
void main() {
    update_status(1);
    update_message("Processing");
    float vals[] = {1.1, 2.2, 3.3};
    update_values(vals, 3);
}
```

## 6. 内容結合（最も強い結合）
内容結合は、あるモジュールが他のモジュールの内部実装に直接アクセスする場合に発生します。
```c
// モジュールA
void process_array() {
    static int internal_array[100];
    static int count = 0;
    
    // 内部配列に値を追加
    internal_array[count++] = count;
    printf("Added value: %d\n", count);
}

// モジュールB - 内部実装に不正にアクセス
extern int internal_array[];
extern int count;

void hack_module_a() {
    // モジュールAの内部変数に直接アクセス
    internal_array[count] = 9999;
    count += 10;
    printf("Hacked internal state!\n");
}

void main() {
    process_array();
    hack_module_a();
    process_array();
}
```
この例では、モジュールBがモジュールAの内部実装詳細（静的変数）に直接アクセスしています。これは非常に強い結合であり、モジュールAの実装変更がモジュールBに即座に影響を与えるため、避けるべきです。
各種結合度は、上から下に向かうにつれて強くなり、コードの保守性や再利用性が低下します。良いプログラム設計では、できるだけ弱い結合（データ結合やスタンプ結合）を目指すべきです。