Hatena::Groupcprogramming

Going My C Way このページをアンテナに追加 RSSフィード

2011年07月19日(火)

プリプロセッサの活用例

21:55 | プリプロセッサの活用例 - Going My C Way を含むブックマーク はてなブックマーク - プリプロセッサの活用例 - Going My C Way プリプロセッサの活用例 - Going My C Way のブックマークコメント

ヘッダファイルの2重読み込み防止とC++で使われた場合のC言語ロケールの宣言。

/* ヘッダファイルの先頭 */
#ifndef INCLUDED_FOO_H
#define INCLUDED_FOO_H

#ifdef __cplusplus
extern "C" {
#endif

   :

#ifdef __cplusplus
}
#endif

#endif /* !INCLUDED_FOO_H */
/* ヘッダファイルの末尾 */

----

C言語規格準拠の判定

#if defined(__STDC__)
        /* C standard */
    #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199001L)
        /* C99 */
    #endif
#endif

処理系GCC であるかの判定

#if defined(__GNUC__)
        /* GCC */
    #if __GNUC__ == 4
        /* GCC4 */
    #endif
#endif

----

条件コンパイルで有効/無効になるステートメントを囲むマクロ

(下例ではマクロDEBUGが定義されているか否かで切り替える)

#if defined(DEBUG)
    #define Debug(Statements_)  Statements_
#else
    #define Debug(Statements_)
#endif

ソースファイルでは以下のようにする。Debug() はステートメントを囲める。

  Debug(
     put_d(a);
     put_s(s);
  )

----

配列素数を求める。array_ にはアドレスでなく配列シンボルを渡す必要がある。

#define elements_of(array_)     (sizeof(array_)/sizeof((array_)[0]))

----

LSB と MSB。

#define LSB         (1U)
#define MSB         (~(~0U >> 1))

----

nビット目のセットとクリア。

#define set_bit(v_, n_)     ((v_) | (1 << (n_)))
#define clear_bit(v_, n_)   ((v_) & ~(1 << (n_)))

----

CTRL-c と Meta-c。

#define CTRL(c_)    ((c_) & 0x1f)
#define META(c_)    ((c_) | 0x80)

ソースでの使用例。

   int c = CTRL('A');    /* CTRL-A (= 0x01) */
   int m = META('A');    /* META-A (= 0xC1) */

----

ソースファイル名と行番号の表示。トレース用。

(Point() という名前はよくないです。。。)

#define Point()     (printf(__FILE__ ":%d\n", __LINE__))

出力例

try.c:45

----

オブジェクトファイルにコンパイル日時を埋め込む。

(ソースファイル(.cファイル)に記述)

static const char *compileDate = "Compiled: __FILE__ " at " __DATE__ " " __TIME__;

コンパイルされたオブジェクトファイル(それがリンクされた実行ファイル)にコンパイル日時が埋め込まれるので、strings などでオブジェクトファイルから探せる。

(下例は try.c から try がコンパイルされた場合)

$ strings try | grep Compiled
Compiled: try.c at Jul 10 2011 22:10:39

GCC で -Wall -Wextra を付けてコンパイルすると変数宣言の部分で以下のような警告がでる。(定義しているのに使ってない、と警告)

try.c:21:20: warning: ‘compileDate’ defined but not used

GCC の __attribute__ を使い以下のように対処する。(警告は出なくなる)

#if defined(__GNUC__)
    #define UNUSED  __attribute__((unused))
#else
    #define UNUSED
#endif

UNUSED static const char *compileDate = "Compiled: " __FILE__ " at " __DATE__ " " __TIME__;
*/

----

変数の簡易出力用マクロは以下の日記