コンテンツにスキップ

03.C言語 コーディング規約

このドキュメントでは、DevBlueprintを利用するプロジェクトでC言語を記述する際の、コーディングスタイルと規約について定めます。 C言語は自由度が高い反面、規約がないとコードの品質に大きな差が生まれるため、一貫したスタイルを保つことが重要です。

共通原則との関係

本規約は、01.共通コーディング原則 をC言語に特化・具体化したものです。必ず共通原則にも目を通してください。


1. 基本方針

  • 本プロジェクトのC言語コードは、可読性、移植性、安全性を最優先します。
  • 特定の歴史的スタイル(例: K&R, GNU)に固執するのではなく、以下の規約で定める、モダンで一貫性のあるスタイルを目指します。
  • 可能な限り、C99以降の標準に準拠することを推奨します。

2. 自動フォーマットと静的解析の活用

手作業でのスタイル遵守は困難なため、ツールの利用を強く推奨します。

  • フォーマッター: ClangFormat
    • 役割: プロジェクトのスタイルを定義した.clang-formatファイルに基づき、コードの見た目を自動で統一します。
    • 運用: コミット前に必ずフォーマッターを実行することをルールとします。
  • 静的解析: Clang-Tidy, Cppcheckなど
    • 役割: コーディングスタイルだけでなく、潜在的なバグ、メモリリークの可能性、未定義動作などをコンパイル前に検出します。CI/CDプロセスに組み込むことを強く推奨します。

3. 命名規則

  • snake_case (スネークケース):
    • 関数名 (void my_function();)
    • 変数名 (int my_variable;)
  • PascalCase (パスカルケース):
    • 構造体 (struct)、共用体 (union)、enumの型定義名 (typedef)。
    • 例: typedef struct MyStruct { ... } MyStruct;
  • UPPER_SNAKE_CASE (大文字のスネークケース):
    • マクロ (#define) や enum のメンバー。
    • 例: #define MAX_BUFFER_SIZE 1024, enum Status { STATUS_OK, STATUS_ERROR };

4. ヘッダーファイル (.h)

  • インクルードガード: 全てのヘッダーファイルには、多重インクルードを防止するためのインクルードガードを必ず記述します。

    #ifndef MY_MODULE_H
    #define MY_MODULE_H
    
    // ... content ...
    
    #endif /* MY_MODULE_H */
    
    #endifの後ろにガード名をコメントとして記述すると、ネストが深くなった際に分かりやすくなります。

  • #includeの順序:

    1. 対応するヘッダーファイル自身(例: my_module.cなら"my_module.h"
    2. C標準ライブラリ(<stdio.h>, <stdlib.h>など)
    3. 外部ライブラリのヘッダー
    4. プロジェクト内の他のヘッダー
    5. この順序は、ヘッダーファイルの自己完結性を保証するのに役立ちます。

5. 安全なコーディングプラクティス

  • コンパイラの警告:
    • コンパイラの警告レベルは、可能な限り高く設定します(例: gcc -Wall -Wextra -Werror)。
    • 全ての警告はエラーとして扱い、修正することを原則とします。 警告を無視してはいけません。
  • ポインターとメモリ管理:
    • ポインター変数は、宣言と同時に初期化します(NULLまたは有効なアドレスで)。初期化されていないポインターは非常に危険です。
    • mallocなどで動的に確保したメモリは、不要になったら必ずfreeで解放します。誰がメモリの所有権を持つのかを常に意識して設計してください。
  • constの積極的な利用:
    • 変更されるべきでない変数やポインター引数には、積極的にconst修飾子を付け、意図しない変更をコンパイラに検出させます。
    • 例: void print_string(const char* str);

6. 要求IDとの連携

  • 01.共通コーディング原則 で定められた通り、機能の実装に対応する要求IDを、関数の直前のコメントとして明記します。
  • パラメータや戻り値の詳細な説明は、02.設計仕様/01.API仕様書 で定義される仕様書に記述し、コードのコメントは簡潔に保ちます。
  • // REQ-AUTH-1.1: ユーザー名とパスワードで認証を行う
    int authenticate_user(const char* username, const char* password)
    {
        // なぜこの処理が必要か、という意図を記述...
        // ...
    }