-1

次のマクロを定義しました。

#define abss(a) a >= 0 ? a : -a

これを呼び出しながら、

int b=-1;
int c = abss(b);
printf("%d\n",c);

b >= 0 の形式で置き換える必要がありますか? b : --b、-2 を出力するはずですが、私の Bloodshed/DevC++ コンパイラ 1 では出力されます。

C言語を調べて調べているので、実際にCで上記のケースがどうなるか知りたいのですが、出力結果1は私の使用しているCPPコンパイラの結果なのか?

4

7 に答える 7

3

あなたのコード

int b=-1;
int c = abss(b);
printf("%d\n",c);

プリプロセッサによって次のように変換されます。

int b=-1;
int c = b >= 0 ? b : -b;
printf("%d\n",c);

( はint b=-1C ドメインにありますが、abss(b)はコンパイラが到達する前にプリプロセッサによって展開されますint b=-1)

于 2012-06-26T10:41:44.587 に答える
2

一体なぜ、-2 を出力する必要があると思いますか?

#define abss(a) a >= 0 ? a : -a

だからこれ: int c = abss(b)

int c = b >= 0 になりますか? b : -b

b は -1 なので、1 に評価されます

ところで、x + 1 のようなものが渡される可能性があるため、マクロ パラメータのすべての使用を括弧で囲む必要があります。

abss(++x) の結果は言うまでもありません

于 2012-06-26T10:46:01.223 に答える
1

このマクロ

#define abss(a) a >= 0 ? a : -a

確かに危険ですが、危険はあなたが思っているところにはありません。あなたの投稿からの表現

int c = abss(b);

完全に正常に動作します。ただし、式が単純な変数ではなく、計算が難しい関数である場合や、副作用のある式である場合はどうなるかを考えてみてください。例えば

int c = abss(long_calc(arg1, arg2));

また

int c = abss(ask_user("Enter a value"));

また

int c = abss(b++);

関数abssである場合、3 つの呼び出しはすべて、予測可能な時間内に良好な結果を生成します。ただし、マクロは最初の呼び出しを呼び出しlong_calcてからask_user2 回実行し (再度プロンプトが表示されたときにユーザーが別の番号を入力するとどうなるでしょうか?)、後置インクリメントがb2 回行われます。

さらに、この一見単純な式を考えてみてください。

int c = abss(b) + 123;

+よりも優先順位が高いため? :、結果の展開は次のようになります。

int c = b >= 0 ? b : -b + 123;

bが正の場合は123加算されないので、式の意味が大きく変わります!

この最後の欠点は、式を括弧で囲むことによって対処できます。また、次のように、各マクロ引数を括弧で囲む必要があります。

 #define abss(a) ((a) >= 0 ? (a) : -(a))
于 2012-06-27T18:32:45.287 に答える
1

マクロは次のように展開されます

b >= 0 ? b : -b;

b >= 0 ? b : --(-b);あなたが期待しているわけではありません。

あなたはそれを示唆していますか

int x = -4;
-x; 

デクリメントする必要がありますxか?

結論- 可能であればマクロの使用は避けてください。

于 2012-06-26T10:40:15.337 に答える
1
#define neg(a) -a

int b = -1;
neg(b);

上記の場合、マクロは-bプリプロセッサによって展開され、値は 1 になります。プリプロセッサは、の内容の符号が負であることさえ認識しません。前置デクリメント演算子?b-

次のように書いたとしても:

 neg( -b );

マクロ置換は、テキストの検索と置換ではなく、トークンレベルで行われます。と同等の結果が得られますが、- ( -b )そうではありません --b

編集:他のコメントでリンクしているマニュアルは古く (C99 標準に対応していません)、危険なほど悪いです。ざっと目を通しただけで、正しいと思い込むと本当にバカに見えるようなステートメントが半ダース見つかりました。着火以外には使用しないでください。

于 2012-06-26T10:38:04.007 に答える
1

マクロプロセッサは、間に空白がなくても、2 つの隣接するトークンを一緒に添付することはありません。実際、他のポスターが言及したように、マクロは- b、または1.

プリプロセッサによって展開されたときに 2 つのトークンを 1 つにしたい場合は、トークンの貼り付け演算子を使用する必要があります。 ##

#define abss(a) a >= 0 ? a : - ## a

マイナス記号と変数が 1 つのトークンを形成するという意味で、これは実際にあなたが望むことを行います。残念ながら (または、見方によっては幸いなことに!) 貼り付けられたトークン "-b" は無効になり、展開はコンパイルされません。

于 2012-06-26T10:44:09.880 に答える
0

The reason for you getting the behaviour is preprocessor will just replace a with b and so effectively your code after preprocessing will be like

b >= 0 ? b : -b

and not

b >= 0 ? b : --b

So, when if b = -1, then it will effectively be considered as -(-1) and thus becomes 1.

You can check the preprocessor output and see it for yourself.

于 2012-06-26T10:47:21.917 に答える