2012-03-24 18 views
0

なぜ結果が36になるのか分かりません。ここで何が起きているのか、プリプロセッサは何をしているのか、誰かに教えてください。C++マクロの副作用

#include <iostream> 
#define QUADRAT(x) ((x) * (x)) 

using namespace std; 

int main() 
{ 
    double no = 4.0; 
    double result = QUADRAT(++no); 

    cout << result; 
    return 0; 
} 

おかげでたくさん:>

答えて

4

この例では、プリプロセッサはQUADRAT(++no)((++no) * (++no))に置き換えます。

2つのインクリメントの間にシーケンスポイントがないという事実がなければ、noが2回インクリメントされるため、実際には未定義の動作が発生しています。誰も何が起こるかを知ることができないので、あなたが見るどんな出力も有効です。

+1

感謝オリー、今それは意味をなさない:) – Max

2

プリプロセッサは、基本的には、コピーアンドペーストエンジンです。マクロはではなく、関数であることに注意してください。代わりに、インライン展開されています。マクロが展開されたときにコードに何が起こるかを考えてください。

+2

セス、私は彼が間違った答えにコメントしたと思います。 –

+0

私はあなたの答えセスを意味しましたが、奇妙なStackoverflowは間違ってそれを投稿したのはオリーだったと私に言った。今あなたの名前はそれより下です:/ – Max

0

は、xの代わりに無++のリテラル置換の一種である何が起こるか、それはあなたが書かれていているよう:

double result = ((++no) * (++no)); 

を結果である何...それは未定義の動作でなければなりません(あなたが得ます36偶然)、そしてg ++と-Wallは私と同意します。

1

このライン:

double result = QUADRAT(++no); 

はこれに展開されます:ので、それはこの方法を実行します

no = no + 1; 
no = no + 1; 
result = no * no; 

:これは動作して終わること

double result = ((++no) * (++no)); 

方法と同じです増分が乗算の前に実行されます。プリプロセッサは、渡したもののテキストコピーを実行するので、 "++ no"は最終コードに2回現れ、結果が計算される前に++のインクリメントは何も起こらない。彼らはあなたのように高速プリプロセッサ定義として何かを与えるだろうが、危険性なし - 最近のほとんどのコンパイラは、テキスト置換を行うことなく、このコードを拡大していきます

inline double QUADRAT(double x) { return x * x; } 

:この問題を解決するための方法は、インライン関数を使用することですあなたが直面しているような問題を抱えています。