14

私は、c の 2 つのよく知られた本で 2 つの異なることを発見しました。最初の 1 つは、「マクロ展開で引用符で囲まれた文字列で正式なパラメーターが置き換えられない」です - K&R c 言語ページ 76

2 つ目はコードです。

#define PRINT(var,format) printf("variable is %format\n",var)
PRINT(x_var,f);

後のマクロ呼び出しは次のように展開されます

printf("x_var is %f\n",x_var);
  • これは ansi c - E. balagurusamy (448 ページ) でのプログラミングによるものです。

確かに、2 つの引用は互いに矛盾しています。私が知る限り、最初のものは真実であり、私のコンパイラはそう結果を出します。しかし、2冊目も有名で人気があります。以前のバージョンの c にそのようなものがあったのか、それとも 2 番目の引用が間違っているのか知りたいです。

4

2 に答える 2

23

2 番目の本は間違っています。マクロがそのように展開されないことを確認するのは簡単です。ただし、プリプロセッサ演算子を使用してトークンを文字列化することで、説明されている効果を得ることができます。#

#define PRINT(var,format) printf(#var" is %"#format"\n",var)

これで、次のように変数を出力できます。

int xyz = 123;
PRINT(xyz, d);

これはideone の作業サンプルへのリンクです

「#format」の前後に二重引用符が追加されていること、および「var」と「format」の前に「#」が追加されていることに注意してください。'#' 演算子により、変数の値が引用符で囲まれた文字列になり、それ自体が二重引用符で囲まれます。これにより、置換された文字列は引用符で囲まれた 4 つの連続した文字列になり、C コンパイラはこれを 1 つの文字列に連結する要求として認識します。したがって、文字列: "xyz"、" is %"、"d"、および "\n" は次のように連結されます: "xyz is %d\n"

(この例は元の質問の例とは異なることに注意してください。元の例には「変数は...」があり、答えは「変数」を「var」マクロ引数のインスタンスに置き換えました)

于 2012-06-27T18:11:18.923 に答える
3

本は正しいです。時間です。私はそれを検証するために小さなテスト プログラムを書きました ( ed.

#define PRINT(fmt,val) printf("val = %fmt\n", (val))
main()
{
    int x;
    x = 5;
    PRINT(d, x);
}

Unix V6 を実行している PDP-11 でコンパイルしました。プログラムを実行すると、次の出力が生成されます。

x = 5

これは K&R C よりも前のことです。この「機能」は、C の後の反復の 1 つで削除され、ISO C90 で公式になりました。

于 2016-04-21T11:58:35.543 に答える