6

以下のコードをウェブサイトで見ました。結果がまたは11の代わりにとして表示される方法を理解できませんでした。2513

なぜ私が考えているの25SQ(5) 5*5

または13理由

SQ(2) = 4;

SQ(3) = 9;

かもしれませんが、最終的な結果は になり13 (9 + 4) ます11。結果はどのようになってい11ますか?

using namespace std;
#define SQ(a) (a*a)
int main()
{
    int ans = SQ(2 + 3);
    cout << ans << endl;
system("pause");
}
4

6 に答える 6

19

プリプロセッサは、ソースコードに対して単純なテキスト置換を行います。基礎となる言語やその規則については何も知りません。

あなたの例では、はにSQ(2 + 3)展開され(2 + 3*2 + 3)、はに評価され11ます。

定義するためのより堅牢な方法SQは次のとおりです。

#define SQ(a) ((a)*(a))

さて、SQ(2 + 3)に展開し((2 + 3)*(2 + 3))、を与え25ます。

この定義は改善されたものですが、それでも防弾ではありません。副作用SQ()のある式に適用された場合、これは望ましくない結果をもたらす可能性があります。例えば:

  • f()がコンソールに何かを出力してを返す関数である場合intSQ(f())出力は2回出力されます。
  • iint変数の場合SQ(i++)未定義の動作になります。

マクロの問題のさらなる例については、マクロの落とし穴を参照してください。

これらの理由から、一般的にはマクロよりも関数を使用することが望ましいです。

于 2012-12-05T07:29:34.263 に答える
6

#defineコンパイラがソース コードを確認する前に展開が開始されます。そのため、それらはプリプロセッサ ディレクティブと呼ばれます。ここでのプロセッサは、C を機械可読コードに変換するコンパイラです。

したがって、これはマクロ プリプロセッサがコンパイラに渡すものです。

SQ(2 + 3)として展開されます(2 + 3*2 + 3)

つまり、これは実際には2 + 6 + 3=11です。

どうすれば期待どおりに動作させることができますか?

  1. 評価の順序を強制します。マクロ定義またはマクロ呼び出しで () を使用します。また
  2. 仕事をする簡単な関数を書く
于 2012-12-05T07:39:28.230 に答える
3

Cプリプロセッサは、コンパイラが式とC構文を一般的に解釈する前に、テキスト置換を行います。したがって、このコードでCプリプロセッサを実行すると、次のように変換されます。

SQ(2 + 3)

の中へ:

2 + 3*2 + 3

これは次のように簡略化されます。

2 + 6 + 3

これは11です。

于 2012-12-05T07:31:12.997 に答える
1

コンパイル前の単なる置き換えです

だからあなたはこれを試してみるべきです:

#define SQ(a) ((a)*(a))

あなたの場合、SQ(2 + 3)は、と同等(2+3*2+3)です11

しかし、私が上で書いたようにそれを修正すると、それは次のようになります、((2+3)*(2+3))それは5*5 = 25あなたが望む答えです。

于 2012-12-05T07:30:30.093 に答える
1

実装では、値は2+3 * 2+32+6+3=11 に展開されます。

次のように定義する必要があります。

#define SQ(x) ({typeof(x) y=x; y*y;})

でテスト済みgcc、次のような入力について

  1. 定数、
  2. 変数、
  3. 定数+定数
  4. 定数+変数
  5. 変数++ / ++変数
  6. printf を含む関数呼び出し。

注:typeof標準 C への GNU 追加です。一部のコンパイラでは使用できない場合があります。

于 2012-12-05T08:22:32.367 に答える
1

#プリプロセッサを定義

構文 : # 識別子の置換を定義

  1. プリプロセッサは、このディレクティブに遭遇すると、コードの残りの部分に出現するすべての識別子を置換で置き換えます。
  2. この置換は、式、ステートメント、ブロック、または単に何でもかまいません。
  3. プリプロセッサは C を理解せず、単に識別子の出現箇所を置換で置き換えます。

# define は、関数マクロを定義するためのパラメーターでも機能します。

# define SQ(a) (a*a)

コンパイル時に SQ(a) の出現を a*a に置き換えます。したがって、

SQ(2+3) は 2+3*2+3 に置き換えられます。置換が完了した後に計算が実行されます。したがって、答えは 2+3*2+3=11 です。

于 2012-12-05T07:42:31.940 に答える