このドキュメントでは、Tilen Majerleがプロジェクトと図書館で使用するCコードスタイルについて説明しています。
GNOME開発者サイトからの引用から始めましょう。
コードを書くときの最も重要なルールはこれです。周囲のコードを確認し、模倣してみてください。
メンテナーとして、周囲のコードとは異なるコーディングスタイルのパッチを受け取ることはがっかりしています。これは、誰かが泥だらけの靴のあるきれいな清潔な家に踏みにじっているように、無礼です。
したがって、このドキュメントが推奨するものが何であれ、すでに書かれたコードがあり、パッチを適用している場合は、それがあなたの好きなスタイルでなくても、現在のスタイルを一貫性に保ちます。
VSCODEには、コード開発中に自動フォーマットツールを使用して開発者を支援する設計であるclang-format
Tool(LLVMパッケージの一部)が事前にインストールされています。
そのため、ユーザーはファイルの変更(および保存)でコードをフォーマットできます。ファイルが保存されると、VScodeはClang-Formatを呼び出してコードをフォーマットしようとします。使用するルールは.clang-format
ファイルです。 Clang-formatが現在のファイルのパスでルールを見つけることができない場合、それが見つかるまでルートまでずっと進みます。まだ利用可能な場合は、デフォルトのルールが使用されます。
このリポジトリには、ルールが説明されたものを一致させる最新の.clang-format
ファイルが常に含まれています。フォルダーをルートまたはプロジェクト、またはソフトウェア開発プロジェクトのルートに配置できます。>すべてのファイルを使用してください!
一部の構成は有効にする必要があります。
キーワードは、このドキュメントで説明されているように解釈する必要があります。
ここに、最も明白で重要な一般的なルールがリストされています。他の章を続ける前に、それらを注意深く確認してください。
clang-format
、このリポジトリに添付されたフォーマットファイルで使用する必要があります(バージョン15.x
は最低です)C11
標準を使用します4
スペースを使用します1
スペースを使用します /* OK */
if ( condition )
while ( condition )
for ( init ; condition ; step )
do {} while ( condition )
/* Wrong */
if ( condition )
while ( condition )
for ( init ; condition ; step )
do {} while ( condition )
int32_t a = sum ( 4 , 3 ); /* OK */
int32_t a = sum ( 4 , 3 ); /* Wrong */
__
または_
プレフィックスを使用しないでください。これは、C言語自体のために予約されていますprv_
名のプレフィックスを優先しますlibname_int_
またはlibnamei_
プレフィックスを優先します。これは、ユーザーアプリケーションが使用しないでください。_
charを使用して、変数/関数/タイプに小文字文字のみを使用しますfor
、 while
、 do
、 switch
、 if
、...) size_t i ;
for ( i = 0 ; i < 5 ; ++ i ) { /* OK */
}
for ( i = 0 ; i < 5 ; ++ i ){ /* Wrong */
}
for ( i = 0 ; i < 5 ; ++ i ) /* Wrong */
{
}
int32_t a ;
a = 3 + 4 ; /* OK */
for ( a = 0 ; a < 5 ; ++ a ) /* OK */
a = 3 + 4 ; /* Wrong */
a = 3 + 4 ; /* Wrong */
for ( a = 0 ; a < 5 ; ++ a ) /* Wrong */
func_name ( 5 , 4 ); /* OK */
func_name ( 4 , 3 ); /* Wrong */
global
変数をデフォルト値(またはNULL
)に初期化しないでください。専用のinit
関数(必要な場合)に実装してください。 static int32_t a ; /* Wrong */
static int32_t b = 4 ; /* Wrong */
static int32_t a = 0 ; /* Wrong */
組み込みシステムでは、システム内のさまざまなメモリ位置にRAMの記憶が散らばることが非常に一般的です。特にユーザーがカスタムRAMセクションを宣言する場合、すべてのケースを処理するのはすぐに難しくなります。スタートアップスクリプトは、デフォルト値(.dataおよび.bss)を設定するために担当しますが、他のカスタムセクションにはデフォルト値が満たされない場合があります。
このような問題に依存しないように、各モジュールのinit関数を作成し、それを使用して、次のようにすべての変数のデフォルト値を設定します。
static int32_t a ; /* OK */
static int32_t b = 4 ; /* Wrong - this value may not be set at zero
if linker script&startup files are not properly handled */
void
my_module_init ( void ) {
a = 0 ;
b = 4 ;
}
void
my_func ( void ) {
/* 1 */
char a ; /* OK */
/* 2 */
char a , b ; /* OK */
/* 3 */
char a ;
char b ; /* Wrong, variable with char type already exists */
}
int
my_func ( void ) {
/* 1 */
my_struct_t my ; /* First custom structures */
my_struct_ptr_t * p ; /* Pointers too */
/* 2 */
uint32_t a ;
int32_t b ;
uint16_t c ;
int16_t g ;
char h ;
/* ... */
/* 3 */
double d ;
float f ;
}
typedef struct {
int a , b ;
} str_t ;
str_t s = {
. a = 1 ,
. b = 2 , /* Comma here */
}
/* Examples of "complex" structure, with or with missing several trailing commas, after clang-format runs the formatting */
static const my_struct_t my_var_1 = {
. type = TYPE1 ,
. type_data =
{
. type1 =
{
. par1 = 0 ,
. par2 = 1 , /* Trailing comma here */
}, /* Trailing comma here */
}, /* Trailing comma here */
};
static const my_struct_t my_var_2 = {. type = TYPE2 ,
. type_data = {
. type2 =
{
. par1 = 0 ,
. par2 = 1 ,
},
}}; /* Missing comma here */
static const my_struct_t my_var_3 = {. type = TYPE3 ,
. type_data = {. type3 = {
. par1 = 0 ,
. par2 = 1 ,
}}}; /* Missing 2 commas here */
/* No trailing commas - good only for small and simple structures */
static const my_struct_t my_var_4 = {. type = TYPE4 , . type_data = {. type4 = {. par1 = 0 , . par2 = 1 }}};
for
ループでカウンター変数を宣言します /* OK */
for ( size_t i = 0 ; i < 10 ; ++ i )
/* OK, if you need counter variable later */
size_t i ;
for ( i = 0 ; i < 10 ; ++ i ) {
if (...) {
break ;
}
}
if ( i == 10 ) {
}
/* Wrong */
size_t i ;
for ( i = 0 ; i < 10 ; ++ i ) ...
void
a ( void ) {
/* Avoid function calls when declaring variable */
int32_t a , b = sum ( 1 , 2 );
/* Use this */
int32_t a , b ;
b = sum ( 1 , 2 );
/* This is ok */
uint8_t a = 3 , b = 4 ;
}
char
、 float
、またはdouble
を除き、常にstdint.h
ライブラリで宣言されたタイプを使用します。 unsigned 8-bit
などのuint8_t
。stdbool.h
ライブラリを使用しないでください。それぞれtrue
またはfalse
に1
または0
使用します /* OK */
uint8_t status ;
status = 0 ;
/* Wrong */
#include <stdbool.h>
bool status = true;
true
と比較しないでください。 if (check_func() == 1)
、 if (check_func()) { ... }
を使用しますNULL
値とポインターを比較してください void * ptr ;
/* ... */
/* OK, compare against NULL */
if ( ptr == NULL || ptr != NULL ) {
}
/* Wrong */
if ( ptr || ! ptr ) {
}
int32_t a = 0 ;
...
a ++ ; /* Wrong */
++ a ; /* OK */
for ( size_t j = 0 ; j < 10 ; ++ j ) {} /* OK */
size_t
を使用してくださいpointer
によって指されたメモリを変更してはならない場合は、常にポインターにconst
を使用しますconst
機能パラメーターまたは変数に常に使用してください。 /* When d could be modified, data pointed to by d could not be modified */
void
my_func ( const void * d ) {
}
/* When d and data pointed to by d both could not be modified */
void
my_func ( const void * const d ) {
}
/* Not REQUIRED, it is advised */
void
my_func ( const size_t len ) {
}
/* When d should not be modified inside function, only data pointed to by d could be modified */
void
my_func ( void * const d ) {
}
void *
を使用し、 uint8_t *
を使用しないでください /*
* To send data, function should not modify memory pointed to by `data` variable
* thus `const` keyword is important
*
* To send generic data (or to write them to file)
* any type may be passed for data,
* thus use `void *`
*/
/* OK example */
void
send_data ( const void * data , size_t len ) { /* OK */
/* Do not cast `void *` or `const void *` */
const uint8_t * d = data ; /* Function handles proper type for internal usage */
}
void
send_data ( const void * data , int len ) { /* Wrong, not not use int */
}
sizeof
備えたブラケットを常に使用してくださいmalloc
およびfree
関数を使用して動的メモリ割り当てを使用するか、ライブラリ/プロジェクトがカスタムメモリ割り当てを提供する場合は、その実装を使用します /* OK */
#include <stdlib.h>
void
my_func ( size_t size ) {
int32_t * arr ;
arr = malloc ( sizeof ( * arr ) * n ); /* OK, Allocate memory */
arr = malloc ( sizeof * arr * n ); /* Wrong, brackets for sizeof operator are missing */
if ( arr == NULL ) {
/* FAIL, no memory */
}
free ( arr ); /* Free memory after usage */
}
/* Wrong */
void
my_func ( size_t size ) {
int32_t arr [ size ]; /* Wrong, do not use VLA */
}
boolean
型として扱われる場合を除き、常に変数をゼロと比較してくださいboolean-treated
変数をゼロまたは1と比較しないでください。代わりに(!)not( !
)を使用します size_t length = 5 ; /* Counter variable */
uint8_t is_ok = 0 ; /* Boolean-treated variable */
if ( length ) /* Wrong, length is not treated as boolean */
if ( length > 0 ) /* OK, length is treated as counter variable containing multi values, not only 0 or 1 */
if ( length == 0 ) /* OK, length is treated as counter variable containing multi values, not only 0 or 1 */
if ( is_ok ) /* OK, variable is treated as boolean */
if (! is_ok ) /* OK, -||- */
if ( is_ok == 1 ) /* Wrong, never compare boolean variable against 1! */
if ( is_ok == 0 ) /* Wrong, use ! for negative check */
/* comment */
を使用してくださいextern
キーワードを使用して、常にC++
をチェックしてくださいstatic
あっても、すべての関数にはdoxygen対応コメントを含める必要がありますforce_redraw
。 forceRedraw
使用しないでくださいvoid *
を返す関数をキャストしないでください。 uint8_t* ptr = (uint8_t *)func_returning_void_ptr();
void *
が他のポインタータイプに安全に促進されるためuint8_t* ptr = func_returning_void_ptr();
その代わり<
>
使用します。 #include <stdlib.h>
""
を使用します。 #include "my_library.h"
uint8_t* t = (uint8_t*)var_width_diff_type
//
から始まるコメントは許可されていません。単一ラインコメントでも、常に/* comment */
を使用してください //This is comment (wrong)
/* This is comment (ok) */
space+asterisk
使用します /*
* This is multi-line comments,
* written in 2 lines (ok)
*/
/**
* Wrong, use double-asterisk only for doxygen documentation
*/
/*
* Single line comment without space before asterisk (wrong)
*/
/*
* Single line comment in multi-line configuration (wrong)
*/
/* Single line comment (ok) */
12
インデント( 12 * 4
スペース)オフセットを使用します。ステートメントが12
インデントを超える場合、コメント4-spaces
次の利用可能なインデントにアライメント(以下の例)にします void
my_func ( void ) {
char a , b ;
a = call_func_returning_char_a ( a ); /* This is comment with 12*4 spaces indent from beginning of line */
b = call_func_returning_char_a_but_func_name_is_very_long ( a ); /* This is comment, aligned to 4-spaces indent */
}
_
文字で区切られている必要があります /* OK */
void my_func ( void );
void myfunc ( void );
/* Wrong */
void MYFunc ( void );
void myFunc ();
/* OK */
const char * my_func ( void );
my_struct_t * my_func ( int32_t a , int32_t b );
/* Wrong */
const char * my_func ( void );
my_struct_t * my_func ( void );
/* OK, function names aligned */
void set ( int32_t a );
my_type_t get ( void );
my_ptr_t * get_ptr ( void );
/* Wrong */
void set ( int32_t a );
const char * get ( void );
/* OK */
int32_t
foo ( void ) {
return 0 ;
}
/* OK */
static const char *
get_string ( void ) {
return "Hello world!rn" ;
}
/* Wrong */
int32_t foo ( void ) {
return 0 ;
}
_
文字を使用して、可変名のすべての小文字を作成します /* OK */
int32_t a ;
int32_t my_var ;
int32_t myvar ;
/* Wrong */
int32_t A ;
int32_t myVar ;
int32_t MYVar ;
type
ごとにローカル変数をグループ化します void
foo ( void ) {
int32_t a , b ; /* OK */
char a ;
char b ; /* Wrong, char type already exists */
}
void
foo ( void ) {
int32_t a ;
a = bar ();
int32_t b ; /* Wrong, there is already executable statement */
}
int32_t a , b ;
a = foo ();
if ( a ) {
int32_t c , d ; /* OK, c and d are in if-statement scope */
c = foo ();
int32_t e ; /* Wrong, there was already executable statement inside block */
}
/* OK */
char * a ;
/* Wrong */
char * a ;
char * a ;
/* OK */
char * p , * n ;
_
単語間の文字を持つ小文字でなければなりませんtypedef
キーワードが含まれる場合があります構造が宣言されると、 3
の異なるオプションのいずれかを使用できます。
_t
サフィックスを含めてはなりません。 struct struct_name {
char * a ;
char b ;
};
_t
サフィックスを含める必要があります。 typedef struct {
char * a ;
char b ;
} struct_name_t ;
_t
含めてはなりません。Typedefパーツの名前の後に_t
サフィックスを含める必要があります。 typedef struct struct_name { /* No _t */
char * a ;
char b ;
char c ;
} struct_name_t ; /* _t */
悪い宣言とその提案された修正の例
/* a and b MUST be separated to 2 lines */
/* Name of structure with typedef MUST include _t suffix */
typedef struct {
int32_t a , b ;
} a ;
/* Corrected version */
typedef struct {
int32_t a ;
int32_t b ;
} a_t ;
/* Wrong name, it MUST not include _t suffix */
struct name_t {
int32_t a ;
int32_t b ;
};
/* Wrong parameters, MUST be all uppercase */
typedef enum {
MY_ENUM_TESTA ,
my_enum_testb ,
} my_enum_t ;
C99
初期化スタイルを使用します /* OK */
a_t a = {
. a = 4 ,
. b = 5 ,
};
/* Wrong */
a_t a = { 1 , 2 };
_fn
サフィックスを使用します /* Function accepts 2 parameters and returns uint8_t */
/* Name of typedef has `_fn` suffix */
typedef uint8_t ( * my_func_typedef_fn )( uint8_t p1 , const char * p2 );
1
しか含まれていない場合でも、開閉巻きブラケットを含める必要があります1
インデントサイズを含めます /* OK */
if ( c ) {
do_a ();
} else {
do_b ();
}
/* Wrong */
if ( c )
do_a ();
else
do_b ();
/* Wrong */
if ( c ) do_a ();
else do_b ();
if
if-else-if
statementの場合、最初の声明の閉じるブラケットと同じ行にelse
必要があります /* OK */
if ( a ) {
} else if ( b ) {
} else {
}
/* Wrong */
if ( a ) {
}
else {
}
/* Wrong */
if ( a ) {
}
else
{
}
do-while
の場合、 while
はdo
パーツの閉鎖ブラケットと同じ行にある必要があります /* OK */
do {
int32_t a ;
a = do_a ();
do_b ( a );
} while ( check ());
/* Wrong */
do
{
/* ... */
} while ( check ());
/* Wrong */
do {
/* ... */
}
while ( check ());
if ( a ) {
do_a ();
} else {
do_b ();
if ( c ) {
do_c ();
}
}
if ( a ) do_b ();
else do_c ();
if ( a ) do_a (); else do_b ();
while
、またはループfor
do-while
ブラケットを含める必要があります /* OK */
while ( is_register_bit_set ()) {}
/* Wrong */
while ( is_register_bit_set ());
while ( is_register_bit_set ()) { }
while ( is_register_bit_set ()) {
}
while
(or、 for
、 do-while
など)が空の場合(組み込みプログラミングの場合はそうです)、空のシングルラインブラケットを使用してください /* Wait for bit to be set in embedded hardware unit */
volatile uint32_t * addr = HW_PERIPH_REGISTER_ADDR ;
/* Wait bit 13 to be ready */
while ( * addr & ( 1 << 13 )) {} /* OK, empty loop contains no spaces inside curly brackets */
while ( * addr & ( 1 << 13 )) { } /* Wrong */
while ( * addr & ( 1 << 13 )) { /* Wrong */
}
while ( * addr & ( 1 << 13 )); /* Wrong, curly brackets are missing. Can lead to compiler warnings or unintentional bugs */
while
do-while
for
を好む: /* Not recommended */
int32_t a = 0 ;
while ( a < 10 ) {
.
..
...
++ a ;
}
/* Better */
for ( size_t a = 0 ; a < 10 ; ++ a ) {
}
/* Better, if inc may not happen in every cycle */
for ( size_t a = 0 ; a < 10 ; ) {
if (...) {
++ a ;
}
}
if
ステートメントは、割り当てまたは関数呼び出し操作にのみ使用できます /* OK */
int a = condition ? if_yes : if_no ; /* Assignment */
func_call ( condition ? if_yes : if_no ); /* Function call */
switch ( condition ? if_yes : if_no ) {...} /* OK */
/* Wrong, this code is not well maintenable */
condition ? call_to_function_a () : call_to_function_b ();
/* Rework to have better program flow */
if ( condition ) {
call_to_function_a ();
} else {
call_to_function_b ();
}
case
ステートメントに単一のインデントを追加しますcase
またはdefault
ステートメントでbreak
ステートメントに追加の単一インデントを使用する /* OK, every case has single indent */
/* OK, every break has additional indent */
switch ( check ()) {
case 0 :
do_a ();
break ;
case 1 :
do_b ();
break ;
default :
break ;
}
/* Wrong, case indent missing */
switch ( check ()) {
case 0 :
do_a ();
break ;
case 1 :
do_b ();
break ;
default :
break ;
}
/* Wrong */
switch ( check ()) {
case 0 :
do_a ();
break ; /* Wrong, break MUST have indent as it is under case */
case 1 :
do_b (); /* Wrong, indent under case is missing */
break ;
default :
break ;
}
default
ステートメントを含めます /* OK */
switch ( var ) {
case 0 :
do_job ();
break ;
default :
break ;
}
/* Wrong, default is missing */
switch ( var ) {
case 0 :
do_job ();
break ;
}
break
ステートメントを入れます。case
ステートメントと同じ行に開くカーリーブラケットを置く switch ( a ) {
/* OK */
case 0 : {
int32_t a , b ;
char c ;
a = 5 ;
/* ... */
break ;
}
/* Wrong */
case 1 :
{
int32_t a ;
break ;
}
/* Wrong, break shall be inside */
case 2 : {
int32_t a ;
}
break ;
}
_
文字を備えた完全に大文字でなければなりません。 /* OK */
#define SQUARE ( x ) ((x) * (x))
/* Wrong */
#define square ( x ) ((x) * (x))
/* OK */
#define MIN ( x , y ) ((x) < (y) ? (x) : (y))
/* Wrong */
#define MIN ( x , y ) x < y ? x : y
/* Wrong */
#define MIN ( x , y ) (x) < (y) ? (x) : (y)
#define SUM ( x , y ) (x) + (y)
/* Imagine result of this equation using wrong SUM implementation */
int32_t x = 5 * SUM ( 3 , 4 ); /* Expected result is 5 * 7 = 35 */
int32_t x = 5 * ( 3 ) + ( 4 ); /* It is evaluated to this, final result = 19 which is not what we expect */
/* Correct implementation */
#define MIN ( x , y ) ((x) < (y) ? (x) : (y))
#define SUM ( x , y ) ((x) + (y))
do {} while (0)
typedef struct {
int32_t px , py ;
} point_t ;
point_t p ; /* Define new point */
/* Wrong implementation */
/* Define macro to set point */
#define SET_POINT ( p , x , y ) (p)->px = (x); (p)->py = (y) /* 2 statements. Last one should not implement semicolon */
SET_POINT ( & p , 3 , 4 ); /* Set point to position 3, 4. This evaluates to... */
( & p ) -> px = ( 3 ); ( & p ) -> py = ( 4 ); /* ... to this. In this example this is not a problem. */
/* Consider this ugly code, however it is valid by C standard (not recommended) */
if ( a ) /* If a is true */
if ( b ) /* If b is true */
SET_POINT ( & p , 3 , 4 ); /* Set point to x = 3, y = 4 */
else
SET_POINT ( & p , 5 , 6 ); /* Set point to x = 5, y = 6 */
/* Evaluates to code below. Do you see the problem? */
if ( a )
if ( b )
( & p ) -> px = ( 3 ); ( & p ) -> py = ( 4 );
else
( & p ) -> px = ( 5 ); ( & p ) -> py = ( 6 );
/* Or if we rewrite it a little */
if ( a )
if ( b )
( & p ) -> px = ( 3 );
( & p ) -> py = ( 4 );
else
( & p ) -> px = ( 5 );
( & p ) -> py = ( 6 );
/*
* Ask yourself a question: To which `if` statement does the `else` keyword belong?
*
* Based on first part of code, answer is straight-forward. To inner `if` statement when we check `b` condition
* Actual answer: Compilation error as `else` belongs nowhere
*/
/* Better and correct implementation of macro */
#define SET_POINT ( p , x , y ) do { (p)->px = (x); (p)->py = (y); } while (0) /* 2 statements. No semicolon after while loop */
/* Or even better */
#define SET_POINT ( p , x , y ) do { /* Backslash indicates statement continues in new line */
( p ) -> px = ( x );
( p ) -> py = ( y );
} while ( 0 ) /* 2 statements. No semicolon after while loop */
/* Now original code evaluates to */
if ( a )
if ( b )
do { ( & p ) -> px = ( 3 ); ( & p ) -> py = ( 4 ); } while ( 0 );
else
do { ( & p ) -> px = ( 5 ); ( & p ) -> py = ( 6 ); } while ( 0 );
/* Every part of `if` or `else` contains only `1` inner statement (do-while), hence this is valid evaluation */
/* To make code perfect, use brackets for every if-ifelse-else statements */
if ( a ) { /* If a is true */
if ( b ) { /* If b is true */
SET_POINT ( & p , 3 , 4 ); /* Set point to x = 3, y = 4 */
} else {
SET_POINT ( & p , 5 , 6 ); /* Set point to x = 5, y = 6 */
}
}
#ifdef
または#ifndef
の使用は避けてください。代わりにdefined()
または!defined()
を使用します #ifdef XYZ
/* do something */
#endif /* XYZ */
if/elif/else/endif
ステートメントを文書化してください /* OK */
#if defined( XYZ )
/* Do if XYZ defined */
#else /* defined(XYZ) */
/* Do if XYZ not defined */
#endif /* !defined(XYZ) */
/* Wrong */
#if defined( XYZ )
/* Do if XYZ defined */
#else
/* Do if XYZ not defined */
#endif
#if
ステートメント内にサブステートメントをインデントしないでください /* OK */
#if defined( XYZ )
#if defined( ABC )
/* do when ABC defined */
#endif /* defined(ABC) */
#else /* defined(XYZ) */
/* Do when XYZ not defined */
#endif /* !defined(XYZ) */
/* Wrong */
#if defined( XYZ )
#if defined( ABC )
/* do when ABC defined */
#endif /* defined(ABC) */
#else /* defined(XYZ) */
/* Do when XYZ not defined */
#endif /* !defined(XYZ) */
文書化されたコードにより、DoxygenはHTML/PDF/LaTex出力を解析して生成することができるため、プロジェクトの初期段階で適切に行うことが非常に重要です。
variables
、 functions
、 structures/enumerations
にドキシゲン対応ドキュメントスタイルを使用します
使用してください、 @
を使用しないでください5x4
スペース( 5
タブ)のオフセットを常に使用してください /**
* brief Holds pointer to first entry in linked list
* Beginning of this text is 5 tabs (20 spaces) from beginning of line
*/
static
type_t * list ;
/**
* brief This is point struct
* note This structure is used to calculate all point
* related stuff
*/
typedef struct {
int32_t x ; /*!< Point X coordinate */
int32_t y ; /*!< Point Y coordinate */
int32_t size ; /*!< Point size.
Since comment is very big,
you may go to next line */
} point_t ;
/**
* brief Point color enumeration
*/
typedef enum {
COLOR_RED , /*!< Red color */
COLOR_GREEN , /*!< Green color */
COLOR_BLUE , /*!< Blue color */
} point_color_t ;
brief
およびすべてのパラメーターのドキュメントを含める必要がありますout
in
ある場合、すべてのパラメーターに注意する必要がありますreturn
パラメーターを含める必要があります。これは、 void
関数には適用されませんnote
やwarning
など、他のdoxygenキーワードを含めることができます:
パラメーター名とその説明の間 /**
* brief Sum `2` numbers
* param[in] a: First number
* param[in] b: Second number
* return Sum of input values
*/
int32_t
sum ( int32_t a , int32_t b ) {
return a + b ;
}
/**
* brief Sum `2` numbers and write it to pointer
* note This function does not return value, it stores it to pointer instead
* param[in] a: First number
* param[in] b: Second number
* param[out] result: Output variable used to save result
*/
void
void_sum ( int32_t a , int32_t b , int32_t * result ) {
* result = a + b ;
}
ref
キーワードを使用してどれを指定しますか /**
* brief My enumeration
*/
typedef enum {
MY_ERR , /*!< Error value */
MY_OK /*!< OK value */
} my_enum_t ;
/**
* brief Check some value
* return ref MY_OK on success, member of ref my_enum_t otherwise
*/
my_enum_t
check_value ( void ) {
return MY_OK ;
}
NULL
)を使用します /**
* brief Get data from input array
* param[in] in: Input data
* return Pointer to output data on success, `NULL` otherwise
*/
const void *
get_data ( const void * in ) {
return in ;
}
hideinitializer
doxygenコマンドを含める必要があります /**
* brief Get minimal value between `x` and `y`
* param[in] x: First value
* param[in] y: Second value
* return Minimal value between `x` and `y`
* hideinitializer
*/
#define MIN ( x , y ) ((x) < (y) ? (x) : (y))
file
とbrief
説明のためにDoxygenアノテーションを含める必要があります(Doxygenを使用する場合) /**
* file template.h
* brief Template include file
*/
/* Here is empty line */
/**
* file template.h
* brief Template include file
*/
/*
* Copyright (c) year FirstName LASTNAME
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* This file is part of library_name.
*
* Author: FirstName LASTNAME <[email protected]>
*/
#ifndef
を含める必要がありますC++
チェックを含める必要がありますC++
チェック外に外部ヘッダーファイルを含めますextern
使用して、後でソースファイルで定義します /* file.h ... */
#ifndef ...
extern int32_t my_variable; /* This is global variable declaration in header */
#endif
/* file.c ... */
int32_t my_variable; /* Actually defined in source */
別の.c
ファイルに.c
ファイルを含めないでください
.c
ファイルは、最初に対応する.h
ファイルを含める必要があります。
ヘッダーファイルにモジュールプライベート宣言を含めないでください
ヘッダーファイルの例(例のためにライセンスなし)
/* License comes here */
#ifndef TEMPLATE_HDR_H
#define TEMPLATE_HDR_H
/* Include headers */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* File content here */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* TEMPLATE_HDR_H */
リポジトリには、 clang-format
ツールの入力構成である、常にデートの.clang-format
ファイルが付属しています。 VSCodeを含む最新のテクノIDEのほとんどとシームレスに統合できます。フォーマットは、各ファイルの保存でその場で行われます。
https://code.visualstudio.com/docs/cpp/cpp-ide#_code-formatting
Astyleは、入力構成に基づいてコードのフォーマットに役立つ素晴らしいソフトウェアです。
このリポジトリには、 AStyle
ソフトウェアで使用できるastyle-code-format.cfg
ファイルが含まれています。
astyle --options="astyle-code-format.cfg" "input_path/*.c,*.h" "input_path2/*.c,*.h"
芸術的なスタイルの構成は時代遅れであり、更新されなくなりました
リポジトリには、 eclipse-ext-kr-format.xml
ファイルが含まれており、Eclipseベースのツールチェーンで使用してフォーマッタオプションを設定できます。
これは、上記のルールを尊重するための変更を備えたK&Rフォーマッタに基づいています。 Eclipseの設定、 Preferences -> LANGUAGE -> Code Style -> Formatter
Tabでインポートできます。