火曜日, 11月 05, 2019

GNU コーディング標準 C言語編(多分前編)

どうもどうもbeepcapだよ。

Twitterにてバカにしたのだが、意外とみんな知らなそうなのでもしかしてと思って調べたら日本語訳が無い。
そりゃ知らん人が多いわけだ。

ということで簡単に訳してみる。(一部超訳)
原文は: GNU Coding Standards: Making The Best Use of C


「5 C言語の最も優れた使い方」

この章では、GNUソフトウェアを作成する際にC言語を使用する最善の方法についてアドバイスします。


「5.1 ソースコードのフォーマット」

幅広い環境で最大限に読みやすくするために、ソース行の長さは79文字以下にしてください。

関数の本体を開始する左中かっこを1列めに配置して、定義することが重要です。いくつかのツールは、C 関数の始まりを見つけるために、1列めで左中かっこを探します。これらのツールは、この方法で書式設定されていないコードでは動作しません。

--- 訳注 ---
func () { //これをやるな

func ()
{ //こうしろと言っている
--- 訳注終わり ---

関数内で左中かっこ、左かっこ、または左大かっこを1列めに入れることは避けてください。
構造体本体を定義する左中かっこは、役に立つ場合は1列めに定義することができます。

また、関数定義では、1列めで関数の名前を開始することも重要です。これは、ユーザーが関数定義を検索するのに役立ち、特定のツールが関数定義を認識するのに役立ちます。
上記に従って標準Cを使用すると、次の形式になります。

static char *
concat (char *s1, char *s2)
{
  …
}
--- ここK&Rにつき略 ---

標準Cでは、引数が1行に収まらない場合は、次のように分割します。


int
lots_of_args (int an_integer, long a_long, short a_short,
              double a_double, float a_float)
…
構造体型や列挙型の場合も同様に、内容全体が1行に収まらない場合、中かっこを1行めに配置します。

struct foo
{
  int a, b;
}
or
struct foo { int a, b; }
--- ここEmacs固有の話なので略 ---

2つの異なるプログラムの書式が異なる場合、ユーザーに問題が発生しないため、書式は要件とは考えません。

しかし、あなたが使用するスタイルが何であれ、1つのプログラム内に複数のスタイルが混合していると視認性が下がるので、一貫して1つのスタイルを使用してください。既存のプログラムに変更を加える場合は、そのプログラムの元々のスタイルに従ってください。

 関数の本体では、推奨されるスタイルは次のようになります。
if (x < foo (y, z))
  haha = bar[4] + 5;
else
  {
    while (z)
      {
        haha += foo (z, z);
        z--;
      }
    return ++x + bar ();
  }
 --- 訳注(インデントずれてませんよ!本当に推奨がこうなの!) ---

 プログラムが左かっこの前とコンマの後にスペースを入れると読みやすくなります。特にコンマの後。

式を複数行に分割する場合は、演算子の後ではなく、演算子の前で分割します。正しい方法は次のとおりです。
if (foo_this_is_long && bar > win (x, y, z)
    && remaining_condition)
同じレベルのインデントで優先順位の異なる 2 つの演算子を使用しないようにしてください。たとえば、次のように記述しないでください。
mode = (inmode[j] == VOIDmode
        || GET_MODE_SIZE (outmode[j]) > GET_MODE_SIZE (inmode[j])
        ? outmode[j] : inmode[j]);
代わりに、インデントで入れ子が表示されるように、追加のかっこを使用します。
mode = ((inmode[j] == VOIDmode
         || (GET_MODE_SIZE (outmode[j]) > GET_MODE_SIZE (inmode[j])))
        ? outmode[j] : inmode[j]);
Emacs がコードを正しくインデントするように、追加のかっこを挿入します。たとえば、次のインデントは、手で行うと綺麗に見えますが、
v = rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000
    + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000;
しかし、Emacsはそれを(醜く)変更します。かっこのセットを追加すると、同じように見栄えの良いものが生成され、Emacs は保持します。
v = (rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000
     + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000);
--- 訳注: それってEmacs固有の問題じゃ・・・ ---

do-whileループは以下の書式が好ましいです.
do
  {
    a = foo (a);
  }
while (a > 0);
フォームフィード文字(control-L)(訳注: 改ページ文字のこと)を使用して、プログラムを論理的な場所 (ただし関数内では除く) のページに分割してください。ページは印刷ページに収まる必要がないため、ページの長さは関係ありません。フォームフィードは、単独で行に表示されます。

--- 訳注: コードを印刷してた時代の名残りですかね?それともTeX用? ---


「5.2 コメントでやるべきこと」

すべてのプログラムは、それが何のためのものであるか簡単なコメントを記載する必要があります。

例: 'fmt - テキストの単純な塗りつぶしのためのフィルター'

このコメントは、プログラムの 'main' 関数を含むソース ファイルの先頭に記載する必要があります。

また、各ソースファイルの先頭に、ファイル名とファイルの全体的な目的に関する1行または2行の簡単なコメントを書いてください。

英語はすべての国のほぼすべてのプログラマが読むことができる言語ですので、英語でGNUプログラムのコメントを書いてください。英語を上手に書けない場合は、英語でコメントを書いて、他の人に書き直してもらいます。英語でコメントを書けない場合は、一緒に仕事をしてくれる人を見つけて、コメントを英語に翻訳してもらってください。

各関数に対して、関数の動作、引数の種類、引数に使用可能な値と値の意味、使用目的を示すコメントを記載してください。C標準の型が慣習的な方法で使用されている場合は、引数宣言の意味をコメントで繰り返す必要はありません。使用に関して非標準のものがある場合(例えば、最初の文字ではなく、文字列の2番目の文字のアドレスである char * 型の引数など)、または期待どおりに動作しない値がある場合(改行を含む文字列など正しく動作する保証がない値)、それらのことを確認して記載してください。

また、重要な戻り値がある場合は、それついても記載してください。

--- Emacsの話なので割愛 ---

引数名を使用して引数の値について説明すると、関数に対するコメントは非常に明確になります。
(C言語では)変数名自体は小文字にする必要がありますが、変数自体ではなく値について話すときは大文字で記述します。したがって、「inode」ではなく「inode の数の NODE_NUM」と記載してください。(英語では"the inode number NODE_NUM")

読者は自分で関数名を確認することができるので、通常、関数名をコメントに記載する必要はありません。
 
コメントが長くて、関数自体が画面の一番下から出る場合は、例外が発生する可能性があります。

--- これは古い記述ですね ---

次のように、各静的変数にもコメントが必要です。
/* 0以外の場合は、表示内の行を与えられた値で切り捨てます。
    0の場合は、切り捨てずに継続することを意味します。 */
int truncate_lines;
ネストされていない短い条件 (ほんの数行) の場合を除き、すべての '#endif' にはコメントが必要です。コメントは、ブロックの識別を含め、終了する条件を示す必要があります。'#else' には、次のコードの条件とブロックの識別を説明するコメントが必要です。
#ifdef foo
  …
#else /* not foo */
  …
#endif /* not foo */
#ifdef foo
  …
#endif /* foo */
しかし、対照的に、'#ifndef'のためにこのようにコメントを書きます。
#ifndef foo
  …
#else /* foo */
  …
#endif /* foo */
#ifndef foo
  …
#endif /* not foo */


-----------------------------==


めちゃくちゃつかれたので前半はここまで、
後半は何年後になるかわからん。

しかし改めて訳してみると、古くさいものの
結構いいことも書いてあるじゃないか・・・
いままでバカにしてごめんよGNU Coding Standard...

でもあのインデント例はキモくて辛い。

4 件のコメント:

匿名 さんのコメント...

>内容全体が1行に収まらない場合、中かっこを1行めに配置します。
誤訳

エヌユル さんのコメント...

改ページ文字の記述もEmacsに関連機能があるからだと思いますね
いや順序が逆で印刷向けにあるからEmacsに関連機能が搭載されたのかな

Citiinc さんのコメント...

財政的に不安定、現金が必要ですか
または、2%の金利で迅速なローンが必要ですか?
Citigroup @ citigroupbankinc911@gmail.comまでご連絡ください
200万ドルから5000万ドルの範囲のローンを提供する
適切な検証が必要であることに注意してください
ローンの支払い
署名済み管理

Citiinc さんのコメント...

財政的に不安定、現金が必要ですか
または、2%の金利で迅速なローンが必要ですか?
Citigroup @ citigroupbankinc911@gmail.comまでご連絡ください
200万ドルから5000万ドルの範囲のローンを提供する
適切な検証が必要であることに注意してください
ローンの支払い
署名済み管理

自己紹介

自分の写真
NetRadioDJ ...since 2003, Programer ...since 1994