2016-02-13 1 views
9

マクロを#define LOGIC_ONE 1と定義し、case文でLOGIC_ONEを使用する場合は、どのタイプがLOGIC_ONEと考えられますか?マクロはどのようなタイプですか?

値1を定義しているので、intと認識されていますか?

+1

の本当の混乱に取得する学習者のための簡単な方法です。 (msvc、gcc、clangはすべて「-E」を受け入れる) – Ben

答えて

19

マクロは単純なテキストの置き換えです。

コンパイラの起動時に、LOGIC_ONEはすでにプリコンパイラによって1に置き換えられています。すぐに1と書いたのとまったく同じです。 (どちらが、この場合には、...リテラルintです)

編集コメントで議論を含める:
あなた(またはあなたのコードへのアクセス権を持つ他の誰かが)あなたの#define LOGIC_ONE 1#define LOGIC_ONE "1"にを変更した場合、それは変化するであろうあなたのプログラム内のその動作はconst char[]リテラルになります。

編集:
この記事は、私が予想よりも多くの注目を浴びたので、私は好奇心のためのものC++ 14 Standardへの参照を追加すると思った:翻訳の

2.2フェーズ[lex.phases]
(...)
4.プリプロセッサディレクティブが実行され、マクロ呼び出しが展開され、 _Pragma単項演算子式が実行されます。 (...)すべての前処理ディレクティブが削除されます。
(...)
7.トークンを区切る空白文字はもはや重要ではありません。各前処理トークンはトークンに変換されます。 (2.6)。得られたトークンは、構文的および意味的に分析され、翻訳単位として翻訳されます。

前述のように、マクロはフェーズ4で置き換えられ、その後は存在しなくなります。 「構文上および意味上の」分析は、コードがコンパイル(翻訳)されるフェーズ7で行われます。

整数リテラルは

2.13.2整数リテラルで指定され [lex.icon]
(...)
整数リテラルはない期間又は指数を有していない数字の列でありますオプションの分離引用符で、値を決定するときに無視されます。整数リテラルは、その基数を指定する接頭辞とその型を指定する接尾辞を持つことができます。
(...)

表5 -

Suffix | Decimal literal  | Binary, octal, or hexadecimal literal 
----------------------------------------------------------------------------- 
none   | int     | int 
      | long int    | unsigned int 
      | long long int   | long int 
      |      | unsigned long int 
      |      | long long int 
      |      | unsigned long long int 
----------------------------------------------------------------------------- 
u or U  | unsigned int   | unsigned int 
      | unsigned long int  | unsigned long int 
      | unsigned long long int | unsigned long long int 
----------------------------------------------------------------------------- 
l or L  | long int    | long int 
      | long long int   | unsigned long int 
      |      | long long int 
      |      | unsigned long long int 
----------------------------------------------------------------------------- 
Both u or U | unsigned long int  | unsigned long int 
and l or L | unsigned long long int | unsigned long long int 
----------------------------------------------------------------------------- 
ll or LL  | long long int   | long long int 
             | unsigned long long int 
----------------------------------------------------------------------------- 
Both u or U |unsigned long long int | unsigned long long int 
and ll or LL |      | 

文字列リテラルは

2.13.5文字列リテラル [lex.string]で指定された整数リテラルのタイプ
(...)
1文字列リテラルは、二重引用符で囲まれた文字列(2.13.3で定義されている)で、オプションでR、u8、u8R、u、uR、U、UR、L、 ... "、R"(...) "、u8" ... "、u8R" **(...)** "、u" ... "、uR" *〜(...) 「〜」、「U」...、UR「zzz(...)zzz」、L「...」、またはLR「(...)」である。
(...)
6変換フェーズ6の後、encoding-prefixで始まらない文字列リテラルは通常の文字列リテラルであり、指定された文字で初期化されます。
7 u8で始まる文字列リテラル(u8 "asdf"など)は、UTF-8文字列リテラルです。
8通常の文字列リテラルとUTF-8文字列リテラルは、狭い文字列リテラルとも呼ばれます。狭い文字列リテラルは "array of n const char"という型を持ち、ここでnは以下に定義される文字列のサイズであり、 の静的記憶期間(3.7)を有する。

+0

Ie. 'LOGIC_ONE'を' int'のように扱うことができますか? – Noobgineer

+0

@Noobgineerは現在の値はyesですが、誰かが '' 1 ''に変更した場合はどうでしょうか。 –

+2

' 1'を扱うことができるような方法で扱えます。 – Anedar

8

LOGIC_ONEは、どこにでも表示されます。コンパイラが関係する限り、LOGIC_ONEは存在しません、それはちょうど1を見ます。あなたの質問は 'is 1 int?'です。その答えは - >あなたがタイプする場所に依存します1

+0

私はコンパイラが '1'か' LOGIC_ONE'を探すかどうかわかりませんでした。明確化のためにありがとう! – Noobgineer

6

マクロは代替テキストです。 1のタイプはconstexpr intです。

11

プリプロセッサの定義には型がありません。基本的には、コードが表示される場所に「ペースト」されています。たとえば、ステートメントでそれを使用するとします。

int foo = LOGIC_ONE; 

次に、整数として解釈されます。 (コンパイラは、プリプロセッサの後に実行され、そのコードはint foo = 1;と表示されます)。

int foo##LOGIC_ONE; 

次に、変数foo1を作成します。 Yuk!

マクロ定義の代替例を取り上げてください。

完全に有効だし、ハローと呼ばれるint型を宣言していますが、定義のための「タイプ」があることを示している
#define LOGIC_ONE hello 
int LOGIC_ONE = 5; 
printf("%d\n", hello); 

からLOGIC_ONEは、コードに遭遇した場所helloは単に置換なかったです。

絶対に必要でない限り、プリプロセッサマクロを使用しないでください。プロフェッショナルコーディング標準では、しばしばプリプロセッサの使用を禁止または厳しく制限しています。マクロを使用するよりも、一般的には、より良い方法があります。たとえば、これらの代替案を考えてみましょう。

static const int LOGIC_ONE = 1; 
enum { LOGIC_ONE = 1 }; 

プリプロセッサは、プリプロセッサは、コンパイラに `-E`を通過しないかを確認するにはC.

+1

詳細な説明ありがとうございます。マクロは、私が使用しなければならないAPIの一部として提供されていましたが、変更は許可されていませんが、私は将来の努力のためにプリプロセッサマクロを避けるためにあなたのアドバイスを取るでしょう! – Noobgineer

+0

私は、トークンの貼り付けはマクロ引数でしか動作せず、一般的にマクロには適用されないと考えましたか? – supercat

+0

非常に限定されたマクロの使用に対する助言はC++では10倍です(この質問にはタグが付いています)。ほとんどの場合、マクロを使って達成できるものは何でも良い型安全な方法です。ファイルの包含、ガードの組み込み、条件付きコンパイルは、前処理の残りの主要なステーです。 – Persixty

関連する問題