-3

C++の勉強を始めたばかりです。そのような質問をお許しください。私の仕事は、円周を計算してテストするマクロを書くことです。

#define _USE_MATH_DEFINES
#include <cmath>

#define LENGTH(radius) (2 * M_PI * radius)

float l1 = LENGTH(1 + 2); // The result should be 18.8495... I have 8.28. Incorrect result.
float l2 = 1 / LENGTH(2); // The result should be  0.07957... Working correctly.

括弧のペアを追加しました:

float l1 = LENGTH((1 + 2)); // Correct result.

余分な括弧を追加せずに正しい結果を得るために、そのようなマクロを作成するにはどうすればよいですか?

4

3 に答える 3

12

使用する:

#define LENGTH(radius) (2 * M_PI * (radius))

あなたが書くとき

float l1 = LENGTH(1 + 2);

define プリプロセッサを使用すると、次のように変換されます

float l1 = 2 * M_PI * 1 + 2
于 2013-01-01T12:46:49.700 に答える
3

常に、常に、マクロの引数をラップしてください()- どんなに些細なことに思えても、遅かれ早かれ必要になります。

もちろん、同じことを行う関数を作成することには、いくつかの利点があります。2. マクロの引数式に違和感がない。

ポイント 2 を説明するために、マクロを使用した次のコードがあるとします。

 // Print 10 lengths, 3, 5, 7, ... 
 int x = 3;
 for(i = 0; i < 10; i++)
 {
      printf("Length of radius %d is %5.2f\n", x, LENGTH(x += 2));
 }

さて、誰かが最適化クラスを受講し、2* 何かを何か + 何かとして実行する方が高速であることに気付きました。そのため、マクロをより高速になるように書き直します。

 #define LENGTH(radius) (((radius) + (radius)) * M_PI)

さて、x+=2マクロにあるLENGTHので、奇妙なことが起こります(同じステートメントで同じ変数が2回更新されるため、未定義の動作になります[はい、2つのシーケンスポイントの間を意味します]。length関数があった場合、次のように完全に機能しますあなたが期待するでしょう。

于 2013-01-01T13:01:00.050 に答える
1

これにはマクロを使用しないでください--あらゆる点でインライン関数の方が優れています

しかし、何が起こっているのかを理解するのは非常に簡単であり、それを理解することは、マクロを避けるのが最善である理由を知るのに役立ちます.

#define LENGTH(radius) (2 * M_PI * radius)

float l1 = LENGTH(1 + 2);

マクロは単純なテキスト置換であるため、上記のコードは次のように置換されます。

float l1 = (2 * M_PI * 1 + 2);

これは明らかに間違った演算子の優先順位を持っています。

于 2013-01-01T17:07:45.360 に答える