プリプロセッサ魔王

今日はCのプリプロセッサ(cpp)の話。

私はまだ未熟者であるから、多用しつつもcppの使い方を知らずにいた。#defineでエラーコードが定義されているとして、エラーコードの名前と値をくっつけた文字列を得る方法。

#define xstr(s) str(s)
#define str(s)  #s
#define errstr(x)  #x"("xstr(x)")"

で、

#define EIO     5      /* I/O error */
    :
  puts(errstr(EIO));

はどうなるか。まさにEIO(5)と表示されるのだ!!

まさに魔王(なんだそりゃ)。この、名前を文字列にする#は知っていたけど、評価した結果を文字列にするためにワンクッション置くってマクロは知らなかったなぁ。info cppより。

strerror()を使えなんていう野暮を言う奴はいないよね。

(追記) 2004-02-17 15:53

こういうことができてしまう#defineが便利なせいでenumが流行らないのだ(むかむかっ)。エラーコードなんてenum使いたいとこなのに。

サンプルコードは以下の通り。

#include <stdio.h><br /> #include <errno.h></p> <p>#define xstr(s) str(s)<br /> #define str(s) #s<br /> #define errstr(x) #x&#8221;(&#8220;xstr(x)&#8221;)&#8221;</p> <p>int main(int argc, char **argv)<br /> {<br /> puts(errstr(EIO));<br /> return 0;<br /> }<br />

どうだ。

私の場合はもっとがんばって、

#define D(x)   case x: return #x"("xstr(x)")";
char *errcode2str(int err);
  switch(err){
  D(EPERM); D(ENOENT); D(ESRCH);
  default: return "Unknown";
  }
}
#undef D

のようにするのが好みだ。そしてソース自体を

 # awk '/^#define[ \t]*E/{print "D("$2");";}' /usr/include/asm/errno.h

のようにして作っていく。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です