私は持っています
#define ADD 5
#define SUB 6
値5と6を指定して、ADDとSUBを印刷できますか?
いいえ。
dシンボルの名前はdefine
プリプロセッサによって削除されるため、コンパイラはそれらを認識しません。
これらの名前が実行時に重要である場合は、プリプロセッサのシンボル名よりも永続的な名前でエンコードする必要があります。おそらく、文字列と整数を含むテーブル:
#define DEFINE_OP(n) { #n, n }
static const struct {
const char *name;
int value;
} operators[] = {
DEFINE_OP(ADD),
DEFINE_OP(SUB),
};
これは、文字列化プリプロセッサ演算子を使用して、#
繰り返しを回避します。
上記を使用すると、ルックアップコードを簡単に記述できます。
const char * op_to_name(int op)
{
size_t i;
for(i = 0; i < sizeof operators / sizeof *operators; ++i)
if(operators[i].value == op)
return operators[i].name;
return NULL;
}
あなたは次のようなことをすることができます
printf("%d", ADD);
そしてそれは5を印刷します
定義について覚えておく必要があるのは、次のとおりです。
定義は、コンパイルされる前にプリプロセッサによってソースコードに置き換えられるため、コード内のADDのすべてのインスタンスは5に置き換えられます。プリプロセッサの後、printfは次のようになります。
printf("%d", 5);
だからあなたの質問に答えるために:
いいえ、あなたはそのようにそれをすることはできません。
はい。ただし、値5
が文字列に関して何らかの形でシンボリックである逆ルックアップメカニズムを介してではありません"ADD"
。aを介して定義されたシンボル#define
は、構造的にプリプロセッサに置き換えられます。ただし、シンプルに保つことができます。
const char *get_name(int value) {
switch(value) {
case ADD:
return "ADD";
case SUB:
return "SUB";
default:
return "WHATEVER";
}
}
#include <stdio.h>
int main() {
printf("%s = %d\n", get_name(ADD), ADD);
printf("%s = %d", get_name(SUB), SUB);
}
最新のCでは、C99以降、これは、指定された初期化子と複合リテラルを使用して、アンワインドの答えよりもはるかに簡単です。
#define DEFINE_OP(n) [n] = #n
#define OPNAMES ((char const*const opNames[]){ \
DEFINE_OPT(ADD), \
DEFINE_OPT(SUB), \
})
inline
char const* getOp(unsigned op) {
size_t const maxOp = sizeof OPNAMES/ sizeof *OPNAMES;
if (op >= maxOp || !OPNAMES[op]) return "<unknown operator>";
else return OPNAMES[op];
}
最新のコンパイラはgetOp(ADD)
、コンパイル時と同じように呼び出しを拡張できるはずです。