[#C言語]恥ずかしいけど、これしらなかった。。

よく、C言語でマクロ書くときに展開時の副作用を避けるために以下の用に記載することがあります。

#define MACRO(a, b) ¥
  do { ¥
    a += b; ¥
    b -= a; ¥
  } while (/* CONSTCOND */ 0) 

この時のwhileはループでは無いので、判定内容は0としておきますが、よく0の前に「/* CONSTCOND */」と記載します。
多くのオープンソースプロジェクトでもこのような記載を見受けるため、私も特に気にせずお決まり的に記載していました。

ところが、ふと調べたところ、これは重要な意味を持っていたのです。
この「/* CONSTCOND */ 」が意味があるというのですよ!!

もしかして、みなさんはご存知でしたか?

lint(1)とは?

実はこのコメント、lint(1)というプログラムに教えるためのコマンドだったのです。
lint(1)とは、コンパイラだけでは解決できないC言語の構文チェックを補助してくれるプログラムのようです。
これは、しらなかった。。。

この他にも様々なコマンドが存在するようです。

/*ARGSUSEDn*/
最初の引数 n だけの使用法を、lint にチェックさせます。n が指定されていない場合は 0 とみなします。(このオプションは、次の関数の -v オプションと同じ動作をします。)

/*CONSTCOND*/ | /*CONSTANTCOND*/ | /*CONSTANTCONDITION*/
次式の定数オペランドについてのエラー情報を保留します。

/*EMPTY*/
if 文の結果発生する空文についてのエラー情報を保留します。この指示語はテスト式の後、セミコロンの前に入れなければなりません。この指示語は、有効な else 文が後に続くときに空白の if 文をサポートするため供給されます。これは、空の else による結果についてのエラー情報を保留します。

/*FALLTHRU*/ | /*FALLTHROUGH*/
case または default というラベルを付けた文へのフォールスルーについてのエラー情報を保留します。この指示語は、ラベルの直前に入れなければなりません。

/*LINTLIBRARY*/
ファイルの先頭に書くと、そのファイルで使用していない関数や関数の引数についてのエラー情報を保留します。これは、-v オプションと -x オプションを使用したのと同じことです。

/*LINTED [message]*/

未使用の変数または関数についての警告を除く、すべての内部ファイルの警告を保留します。この指示語は、lint の警告が起こった場所の直前に入れなければなりません。-k オプションは、lint がこの指示語を扱う方法を変えます。エラー情報を保留する代わりに、lint は、注釈に追加エラー情報があればそれを出力します。この指示語は、lint 後のフィルタリングのために -s オプションと共に使用すると便利です。

/*NOTREACHED*/
適切な所で、到達できないコードについての注釈を停止します。(この注釈は、通常、exit(2) などの関数を呼び出した直後に入れます。)

/*PRINTFLIKEn*/
lint に通常どおり最初の (n-1) 引数チェックをさせます。n 番目 の引数が、残りの引数をチェックするための printf 形式の文字列と解釈されます。

/*PROTOLIBn*/
n が 0 以外の場合、lint に、関数宣言プロトタイプを関数定義として扱わせます。この指示語は、指示語 /* LINTLIBRARY */ と一緒の場合のみ使用できます。n が 0 の場合、関数プロトタイプは通常どおりに扱われます。

/*SCANFLIKEn*/
lint に通常どおり最初の (n-1) 引数チェックをさせます。n 番目の引数が、残りの引数をチェックするための scanf 形式の文字列と解釈されます。

/*VARARGSn*/
下記の関数宣言でさまざまな数の引数の通常のチェックを保留します。最初の n 引数のデータ型がチェックされます。n が指定されていない場合は、0 とみなされます。新しいコードまたは更新されたコードでは、省略記号ターミネータ(. . .)の使用を勧めます。

「/*CONSTCOND*/」以外だったら「/*NOTREACHED*/」とかも使いそうですね。

ただし、lintと言うのはデフォルトでは動いていないようです。
以下の記事、先頭にあるように、多くの場合、gccが出す警告で満足しているようです。

5.1 予防的メンテナンス(lint)

あわせて読む

コメントを残す