ちかん、かっこわるい。

CPPの#と##の話ですけどね。置換演算子。教えて前園、じゃなくて識者の皆様。ゾノはかえってよろしい。
最近、C90で未定義/処理系依存の機能はすべて悪、即刻禁止せよ、という、やや極端なコーディング規約と格闘しておりましてね。もちろん、関数に渡る引数の評価順序とか、納得できるものから、stdioとかsignalとかexec系とか、それを通り一遍に一律禁止ってのはちょっとないだろってものまであるので、噛み砕いた説明や回避策を作ったりして関係者の最大幸福を達成すべく折衝しておりましゅ。こんなもん極論すれば政治だからなあ。Mさん、マジでレビューありがとうございます。あれはご苦労様でした。
それは置いて、その置換演算子。これが複数あった場合の評価順は処理系依存なのでヨクナイと。極端なキョクたん(今命名)、そうおっしゃる。さいとうは禁止事項ひとつひとつに「ほら、こういう時に使ったりするでしょ、でもそれがこうダメなにょ」というサンプルコードをいちいちいちいちいちいちいちいち書いてはや数日、だがこの置換演算子を複数使う例が浮かばない。にょとか言ってるからダメなのか。そうだったそうだった。
ともかくだ、#が一個なら、assert()とかSTRING()あたりがちょうどいいかなと。

#define assert(p)  ((e) ? (void)0 : fprintf(stderr, "assertion failed: %s", #e))
#define STRING(x) #x

本当は__assert()とか別にマクロなり関数切って__FILE__と__LINE__が、ってのは置いといてね。#一個の話。でも一個は別に禁止されてない。問題は#2個以上、##2個以上、#と##の混在。この例が思いつかない。「ほらあの***のソースの***で使ってるの、あれあれ」と言えない。色々とヘッダも検索してるんだが、なかなか複数の例がない。自分の浅学を実感し、ぢっと手を見る。ソースを使えルーク。そう書いてある。手にそう書いてある。「卵を使い切ること」の下に書いてある。キョクたんがこっちを見ている。
卵を焼いていて(ウソ)かろうじて思いついた、##が複数の例。マルチプラットフォーム対応のコードで、OSの下位APIがプラットフォームごとにdo_something_x86とかdo_something_arm9とか分かれてる場合、APIのテーブルをひとつのヘッダだけで作るとき、

#define API_DECL(platform, command) \
  int do_##command##_##platform(void *data);

/* 以下の powerpc はうまくパラメータとしてコンパイル時に渡るといいなあ */
API_DECL(powerpc, ram_read);
API_DECL(powerpc, ram_read_nocache);
API_DECL(powerpc, dma_start);

...いや、ねえな。ねえよ。ファイル分けたが楽だよ。カーネル内部だと結構泥臭いのがあるかなあ。最近出来合いのバイナリで満足してるからソースないや。linuxあたりを参考に見ようかな。
ともあれ、「こういう使い方があるんじゃぼけ」って方、お待ちしておりマッスル。
あ、##1個はこれがいいかな。おれは明示的にキャストするけども。stdint.h。

#define INT32_C(v)   (v ## L)
#define INT64_C(v)   (v ## LL)
#define UINT8_C(v)   (v ## U)
#define UINT16_C(v)  (v ## U)
 :

定数用。いやでもだから腹痛じゃなくて複数使用の話だっつーの。えーん。検索したなかで、##2つ以上使ってるのはXのXlibint.hでGetReq作ってるくらい。これが典型例、ってのも、ちょっとなあ。あとはcurl, openldap, tcl のヘッダには ## のマクロ定義があるけど、これソースで使ってるのかな。...あー、もういや。切れた。オレ使わねえもん複数なんて。しらないぷーん。...いやいや、そう言っていては折衝ができない。ジジイはトニカク論で押すからな。押し返さんと。キョクたんはまだこっちを見ている。...あれ、もしかしてこのサンプル、英語もいるんでないの? >Mさん
まあさ、さいとうでしょ、見た目わるいっしょ、だからそういう時は「うるせえな、オレが使うなっつったんだ、使うな。髪洗え、くせえぞ、なんだそのスニーカー」って言えば済むっちゃあ済むんだけどね。それはオイラの真意では、あんまり、ない。髪は洗ってほしいが。