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
の順序:- 対応するヘッダーファイル自身(例:
my_module.c
なら"my_module.h"
) - C標準ライブラリ(
<stdio.h>
,<stdlib.h>
など) - 外部ライブラリのヘッダー
- プロジェクト内の他のヘッダー
- この順序は、ヘッダーファイルの自己完結性を保証するのに役立ちます。
- 対応するヘッダーファイル自身(例:
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) { // なぜこの処理が必要か、という意図を記述... // ... }