3

#define引数にスペースを入れてはならないという概念に戸惑いました。

(唯一の制限は、マクロ名と直前のブラケットの間にスペースを入れてはならないことだと思います。私は正しいですか?()括弧内にもスペースを入れてはいけませんか?

以下の表記は正しいですか?

#define AVERAGE_NUMS( min_val, max_val ) ((min_val + max_val) / 2)

皆さん、上記の #define C++ ステートメントは単なる例です。#define を使用している間、実際にスペースが気になります。とにかくあなたの答えをありがとう。

4

4 に答える 4

6

はい、正しいです。ただし、各引数を括弧で囲む必要があります

#define AVERAGE_NUMS( min_val, max_val ) (((min_val) + (max_val)) / 2)

演算子の優先順位の問題を回避します。

于 2013-02-24T12:05:30.013 に答える
4

あなたは正しいです。マクロ名と直後の開き括弧の間にスペースはありません。他の場所のスペース == 問題ありません。

マクロ引数に使用される名前に注意してください。引数と同じ名前の変数がある場合、奇妙なことが起こります...たとえば、例では引数はmax_valですが、入力Max_valしましたしたがって、たまたまこのマクロを使用した変数があった場合Max_val、コードは正常にコンパイルされますが、他の場所ではコンパイルされません...

個人的には、このような状況を回避するために、常にマクロ名に接頭辞 _ を付けています...しかし、純粋主義者は、アンダースコアは予約されており、使用すべきではないと私に言いましたが、それらを詰め込んでください:)

于 2013-02-24T12:06:17.613 に答える
3

Cでは、そのような小さな計算にマクロを使用する場合、次のように式の各パラメーターを常に括弧で囲む必要があります。

#define AVERAGE_NUMS(min_val, max_val) (((min_val) + (max_val)) / 2)

マクロの引数リスト内のスペースはオプションであるため、「害」はありません。すでに述べたように、開き括弧ののスペースはマクロの意味を変更します。その後、パラメーターをとらず、その出現箇所を、パラメーター リストにしたいものと「式」の両方に置き換えます。

括弧内の式に引数を入れないと、演算子の優先順位によって式が変わる可能性があるため、奇妙な結果が生じる可能性があります。これは、マクロが単なるテキスト置換規則であり、プログラミング言語 (C) をまったく尊重しないためです。

失敗する小さな例 (これは奇妙な例ですが、「通常の」使用法が失敗するマクロとして作成する関数は他にもあります):

AVERAGE_NUMS(1 << x, y)

マクロ定義を使用すると、これは次のように展開されます

((1 << x + y) / 2)           // Operator precedence:  1 << (x + y)

しかし、上記のマクロ定義を使用すると、次のように展開されます。

(((1 << x) + (y)) / 2)       // Operator precedence:  (1 << x) + y

C++ では、本当に必要でない限り、マクロを使用しないことを強くお勧めします。

型を指定せずに 2 つの数値の平均を計算するためのより良い方法は、テンプレート メソッドを使用することです。

template<typename T>
T average_nums(T min_val, T max_val) {
    return (min_val + max_val) / T(2);
}

パフォーマンスが気になる場合は、最新のコンパイラはすべて、このコードをマクロ定義と同じ方法で処理することに注意してください。つまり、コードをインライン化します。これは、関連する関数呼び出しがないことを意味しますが、式avg(a, b)は に置き換えられ(a + b) / 2ます。

これとマクロの違いは、マクロはプリコンパイル中に発生する単なるテキスト置換であるため、実際のコンパイル ステップ(a + b) / 2では、avg(a, b).

于 2013-02-24T12:05:43.230 に答える
3

1999年のC標準からの次の抜粋は、マクロ内でスペースがどのように扱われるかという問題をカバーしていると思います.オブジェクトのようなマクロを区別する場合を除いて、スペースはトークンセパレーターにすぎないと実際に述べています.関数のようなマクロは、マクロ名とその直後の開き括弧の間にスペースがあるかどうかに基づいています。

5.1.1.2 翻訳フェーズ

...

1.3The source file is decomposed into preprocessing tokens and sequences of white-space characters (including comments). ... Each comment is replaced by one space character. New-line characters are retained. Whether each nonempty sequence of white-space characters other than new-line is retained or replaced by one space character is implementation-defined.

1.4Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. ... All preprocessing directives are then deleted.

1.7White-space characters separating tokens are no longer significant.各前処理トークンはトークンに変換されます。結果のトークンは、構文的および意味的に分析され、翻訳単位として翻訳されます。

...

6.4 字句要素

構文

トークン:

  • キーワード
  • 識別子
  • 絶え間ない
  • 文字列リテラル
  • 句読点

preprocessing-token:

  • ヘッダー名
  • 識別子
  • pp 番号
  • 文字定数
  • 文字列リテラル
  • 句読点
  • 上記のいずれにもなり得ない各非空白文字

セマンティクス

... Preprocessing tokens can be separated by white space; this consists of comments (described later), or white-space characters (space, horizontal tab, new-line, vertical tab, and form-feed), or both. As described in 6.10, in certain circumstances during translation phase 4, white space (or the absence thereof) serves as more than preprocessing token separation.... ...

6.10 前処理指令

構文

...

  • # 識別子置換リストの改行を定義
  • # define identifier lparen identifier-listopt ) replacement-list new-line
  • # define identifier lparen ... ) replacement-list new-line
  • # define identifier lparen identifier-list , ... ) replacement-list new-line

lparen:

  a ( character not immediately preceded by white-space

6.10.3 マクロ置換

制約

3There shall be white-space between the identifier and the replacement list in the definition of an object-like macro.

セマンティクス

10 フォームの前処理ディレクティブ

  • # define identifier lparen identifier-listopt ) replacement-list new-line
  • # define identifier lparen ... ) replacement-list new-line
  • # define identifier lparen identifier-list , ... ) replacement-list new-line

function-like関数呼び出しと構文的に似た、引数を持つマクロを定義します。

于 2013-02-24T12:40:02.277 に答える