1

C では、次のような関数またはマクロを作成したいと考えています。

void Log(char* what, ...) 

... は const char* のキーと値のペアでなければなりません。これに従わないコードがコンパイル時に爆発することを本当に望んでいます。これを行う __attribute((..)) ディレクティブを探してみましたが、役に立ちませんでした。何か案は?

4

3 に答える 3

3

C には、任意の可変個引数に対してタイプ セーフを適用する方法がありません。GCC と Clang には__attribute__、いくつかの固定ケース用の s があります (可変引数関数で最後の引数が であると予想されるNULL場合は を使用できます__sentinel__; または書式文字列の場合は を使用できますformat)、一般的な解決策はありません。

一方、C++11 にはこの問題を解決するための可変個引数テンプレートがありますが、C で作業しているとのことなので、うまくいきません。

于 2014-01-22T22:49:51.850 に答える
1

さて、私は回避策を見つけました:

#define ASSERT_LIST_TYPE(t, l...) do{t _t[] = {l};}while(0)

void _Log(char* what, ...);

#define Log(what, args...) do{\
  ASSERT_LIST_TYPE(char*, args);\
 _Log(what, args);\
}while(0)

ダミー配列の初期化が正しいタイプではないため、引数が正しいタイプでない場合、少なくとも警告が生成されます。

念のため、これがデバッグ ビルドでない場合は、ASSERT_LIST_TYPE を #ifdef する予定です。

** 編集 **

ここでのフィードバックに基づいて、コードを次のように変更しました。

void _Log(char* what, const char** args, size_t args_len);

#define Log(what, args...) do{\
  const char* a[] = {args};\
  _Log(what, a, (sizeof a)/sizeof(char*));
}while(0)

これは args が空の場合でも機能するように見え、代わりに obj-c リテラル文字列 ("..." ではなく @"...") を渡す人をキャッチします。

于 2014-01-23T01:53:46.497 に答える