コンテンツにスキップ

最終更新:2026-10-12

libcurl C++ 開発メモ

コードスタイルの統一は、チームでの協働やコードレビューに役立ちます。業界でよく使われているのは google のスタイルですが、今回はちょっと違う視点で、私たちが普段よく使っているツールである curl チームのコーディング規約がどのようなものかを見てみましょう。

curl を簡単に説明すると、コマンドラインやスクリプトでデータを転送するのに非常に便利で、皆さんも使ったことがあるはずです。そのソースコードの実装は GitHub で見られます

https://github.com/curl/curl

以下、いくつかの側面から curl の C 言語開発規約を見ていきましょう。

命名

新しい関数や変数の名前は、論理的で理解可能なものにし、その用途に基づいて命名すべきです。

ファイルローカルな関数は static として宣言し、小文字の名前にすることをお勧めします。

インデント

インデントにはスペースのみを使用し、タブは使用しません。新しい開き括弧ごとに 2 つのスペースを使用します。

if(something_is_true) {
  while(second_statement == fine) {
    moo();
  }
}

コメント

C89 コードを書いているため、// コメントは使用できません。// コメントが導入されたのは C99 規格からです。/* コメント */ のみを使用します。

/* 这是一个注释 */

長い行

curl のソースコードは 79 桁を決して超えてはいけません。大きな画面と高解像度の時代になった今でも、これを守るべき理由が 2 つあります:

  1. 幅の狭い列は幅の広い列よりも読みやすいです。新聞が何十年、いや何世紀にもわたって列を使ってきたのには理由があります。
  2. 幅の狭い列により、開発者は異なるウィンドウで複数のコード断片を並べて表示しやすくなります。同じ画面上に 2 つや 3 つのソースコードウィンドウを、複数の端末やデバッグウィンドウと並べて表示できます。

波括弧

if/while/do/for 式では、開き括弧をキーワードと同じ行に書き、閉じ括弧を最初のキーワードと同じインデントレベルの行に置きます。次のように:

if(age < 40) {
  /* 显然是年轻人 */
}

1 行のみの文しか含まない場合は、波括弧を省略できます:

if(!x)
  continue;

関数の場合、開き括弧は独立した行に書くべきです:

int main(int argc, char **argv)
{
  return 1;
}

'else' は次の行に

波括弧を使った条件式に else 節を追加するときは、閉じ括弧の後の新しい行に追加します。次のように:

if(age < 40) {
  /* 显然是年轻人 */
}
else {
  /* 可能是脾气暴躁的 */
}

括弧の前にスペースを入れない

if/while/do/for 式を使用するとき、キーワードと開き括弧の間にスペースを入れてはいけません。次のように:

while(1) {
  /* 永远循环 */
}

ブール条件を使用する

if/while 条件では、次のように書くのではなく、ブール値と TRUE または FALSE、ポインタと NULL または != NULL、整数とゼロまたは非ゼロのように条件値をテストすることを好みます:

result = do_something();
if(!result) {
  /* 出现了问题 */
  return result;
}

条件の中で代入しない

可読性を高め、条件の複雑さを減らすため、if/while 条件の中で変数への代入は避けてください。このようなスタイルは推奨されません:

if((ptr = malloc(100)) == NULL)
  return NULL;

代わりに、より明確な書き方が推奨されます:

ptr = malloc(100);
if(!ptr)
  return NULL;

新しいブロックは新しい行に

同じ行に複数の文を決して書いてはいけません。短い if() 条件であっても例外ではありません。

if(a)
  return TRUE;
else if(b)
  return FALSE;

決してこのようにしないでください:

if(a) return TRUE;
else if(b) return FALSE;

演算子の周りにスペース

C の式では、演算子の両側にスペースを使用してください。ただし、後置の (), [], ->, ., ++, -- と単項の +, -, !, ~, & 演算子は例外で、スペースを付けてはいけません。

例:

bla = func();
who = name[0];
age += 1;
true = !false;
size += -2 + 3 *

 (a + b);
ptr->member = a++;
struct.field = b--;
ptr = &address;
contents = *pointer;
complement = ~bits;
empty = (!*string) ? TRUE : FALSE;

戻り値に括弧を付けない

'return' 文に余分な括弧は付けません:

int works(void)
{
  return TRUE;
}

sizeof の引数に括弧を付ける

コードで sizeof 演算子を使用するときは、その引数の周りに括弧を付けることを好みます:

int size = sizeof(int);

列の整列

行が長すぎる、文が読みにくすぎる、上記の他のスタイルガイドによる、などの理由で、一部の文は 1 行では完了できません。そのような場合、文は複数行にまたがります。

継続行が式または部分式の一部である場合、文のどの部分なのかがはっきり分かるように、適切な列で揃えるべきです。演算子を継続行の行頭に置いてはいけません。それ以外の場合は、2 スペースのインデントガイドラインに従います。以下は libcurl からの例です:

if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
   (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
   (handle->set.httpreq == HTTPREQ_GET ||
    handle->set.httpreq == HTTPREQ_HEAD))
  /* 没有要求 HTTP/1.0 并且是 GET 或 HEAD 请求 */
  return TRUE;

括弧がない場合は、デフォルトのインデントを使用します:

data->set.http_disable_hostname_check_before_authentication =
  (0 != va_arg(param, long)) ? TRUE : FALSE;

関数呼び出しでは開き括弧に合わせます:

if(option) {
  result = parse_login_details(option, strlen(option),
                               (userp ? &user : NULL),
                               (passwdp ? &passwd : NULL),
                               NULL);
}

「現在開いている」括弧に整列させます:

DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
             "server response left\n",
             (int)clipamount));

プラットフォーム関連コード

条件付きコードには #ifdef HAVE_FEATURE を使用します。#ifdef 行で特定の OS やハードウェアをチェックすることは避けています。HAVE_FEATURE は configure スクリプトが Unix 系システム用に生成するべきもので、他のシステムでは config-[system].h ファイルにハードコードされます。

また、libcurl のビルド時には、空または定数として定義される可能性のあるマクロ/関数を使用して、コードをシームレスにすることを推奨します。次の例のように、magic() 関数はビルド時の条件に応じて異なる動作をします:

#ifdef HAVE_MAGIC
void magic(int a)
{
  return a + 2;
}
#else
#define magic(x) 1
#endif

int content = magic(3);

構造体を typedef しない

構造体を使うことはできますが、typedef はしないでください。それらは struct name の形式で識別します:

struct something {
   void *valid;
   size_t way_to_write;
};
struct something instance;

このようにしないでください:

typedef struct {
   void *wrong;
   size_t way_to_write;
} something;
something instance;

本文は次から翻訳しました:https://curl.se/dev/code-style.html

説明

この記事は開発メモです。公式の libcurl ドキュメントと、実際のプロジェクトでのエラーコードの調査と併せてご利用ください。

関連トピック

コメント