-2

私は定数変数の値を変更しようとしています。はい、私は自分がしていることの矛盾を認識していますが、私の狂気への方法があります。

4dmと呼ばれるC /C ++に非常によく似た言語で書いているのがわかりますが、関数以外のコードは許可されていないため、プリプロセッサコマンドを使用してこれを克服しようとしています。その理由は、私がその言語の専門化の形を達成できるようにするためです。この最初のステップは、定数文字列を編集できるようにすることです。

これは別の言語ですが、プリプロセッサはCおよびC++コンパイラとまったく同じように動作します。

#define MY_STR "abc"
#define CONCAT(s) \
    #define TEMP MY_STR \  // store MY_STR in TEMP_STR
    #undef MY_STR \        // undefine MY_STR
    #define MY_STR TEMP s  // redefine MY_STR so it contains the old value plus the new one

CONCAT(def)
printf("%s\n", MY_STR);  // should hopefully print out "abc def"

以下は文字列を連結する簡単な試みですが、MY_STR is not definedこれを修正する方法についてのアイデアを示すコンパイルエラーが発生しますか?

#define MY_STR abc
#define TEMP MY_STR
#undef MY_STR
#define MY_STR TEMP def

void test()
{
    print(MY_STR);
}
4

3 に答える 3

2

#define最初の例では、マクロをプリプロセッサ コマンドに展開しようとしています。それはできません。プリプロセッサはCコード (または何でも) を生成し、マクロ展開でプリプロセッサ ディレクティブのように見えるさまざまなものは、実際にはプリプロセッサ ディレクティブではありません。#マクロ定義には「stringify」演算子があり、その後にマクロパラメーターが続く必要があるため、エラーが発生します。(また、\は行末にある必要があります。その後にコメントを付けることはできません。)

2番目の例では、次のように記述します。

#define TEMP MY_STR

それはまさにそれが行うことです: マクロTEMPを値MY_STR( のマクロ展開でMY_STRはなく、6 文字のトークンMY_STR.

その後、あなたは

#define MY_STR TEMP def

これは、マクロMY_STRを 2 つのトークンTEMPととして定義しdefます。

次に展開しますMY_STR

print(MY_STR);

に置き換えられTEMP defます。展開は再びマクロ プロセッサを介して実行され、これによりTEMPが に置き換えられMY_STRます。これは再びマクロ プロセッサを介して実行されますが、そのマクロの展開内でマクロを展開できないため、今回MY_STR展開されません。したがって、今回はそのままで、最終的には次のようになります。MY_STR

print(MY_STR def);

MY_STRが定義されていない (マクロは定義ではない) ため、コンパイラはそれが定義されていないと文句を言いMY_STRます。

于 2013-02-11T05:20:23.770 に答える
0

優れたコンパイラは、書き込み保護としてマークされるブロックに文字列定数を配置し、それを変更しようとすると、何らかの OS 例外が発生します。

ただし、それはここで行っていることではありません。古い文字列に関して新しい文字列を定義しています。これは C と C++ で機能し、おそらくあなたの言語でも機能します。

あなたはあなた自身の言語を定義しているので、あなたはそれがどのように反応するかを私たちよりもよく知っているでしょう!

于 2013-02-11T04:50:47.930 に答える
0

で達成しようとしていることについてCONCAT、C99標準の§6.10.3.4 ¶3は次のように述べています(部分引用):

結果として完全にマクロ置換された前処理トークン シーケンスは、前処理ディレクティブに似ていても、前処理ディレクティブとして処理されません。

于 2013-02-11T04:52:34.120 に答える