2016-05-02 1 views
1

、私は、3回AAを定義するには、それが合法的である?:の#define何度も、それは合法です?

#include<stdio.h> 
#define AA 10 
#define AA 20 
#define AA 30 
int main() { 
    printf("AA"); 
} 
+4

あなたのコンパイルコマンドで '-Wall'を追加し、それが何を伝えているかを見てください。 – LPs

+3

違法ではありませんが、このように使うのは悪い考えです。コンパイル中に警告を無視しないでください。 –

+1

法律:はい - 有用であり、いい考えです:いいえ。しかし、Cでは、有用でも良いアイデアでもない多くの構造を使用することができます。 ) – tofro

答えて

5

明らかにしても、それがコンパイルできると思っ推奨されません。 あなたの例では、ただ#define AA 30を一度使うことができます。他のケースではあなたはそれがまだ定義されていない場合、マクロを定義したい場合は、あなたが条件文を使用することができます。printf("AA");だけでリテラル文字列を出力しますので、また

#ifndef AA 
#define AA 30 
#endif 

、私は、あなたがマクロを印刷するprintf("%d\n", AA);を意味だと思いますAAprintf("%d", AA);

「AA」が再定義されていることを2つの警告が生成されますgccでそれをコンパイル:

+0

@LPこれは議論の余地がありますが、コンパイルによって再定義が警告されますが、展開は30 – fluter

+1

はい。私が書いたことは間違いありません。 OPコードは30を与え、あなたは何か違うものを与える。 – LPs

+0

私はそれを取得できませんか?どういう意味ですか? – fluter

3

は便利なものにあなたのprintfを補正することによって開始します。警告は本当に重要であり、Cでは避けるべきですが、結果は期待通りです(30)。

6

いいえ、それはありません。 C標準は明確、それは制約違反であること6.10.3 P.2を述べ:

現在のオブジェクトのようなマクロとして定義される識別子が第二定義しない限り、別の #define前処理指令によって再定義 てはなりませんオブジェクトのようなマクロ定義であり、2つの置換リストは と同一です。

すべての制約違反について、コンパイラは説明用のメッセージである「診断」のみを発行するよう義務付けられています。あなたのコードをコンパイルし続けるかもしれません。

より直接的に言えば、コードが間違っていて、コンパイラがあなたに指示しなければなりません。

9

これは、CとC++の両方では有効ではありません。ドラフトC標準N1570から

引用:

6.10.3マクロ置換

制約

1 TwのO交換リストがあれば同一であり、両方で前処理トークンは ている場合のみ同じ番号、順序、スペル、およびホワイトスペースの区切りであり、すべてのホワイトスペースが同じものとみなされます。第ドのfi nitionは、オブジェクトのようなマクロ ドのfi nitionであり、2つの置換リストが同一でない限り、オブジェクトのようなマクロとして定義さ

2識別子現在デFiは別の #defineプリプロセッサディレクティブによって定義さレーデFiがあってはなりません。同様に、第2の定義がパラメータの数と綴りが同じである関数のようなマクロ定義 でないかぎり、関数形マクロとして定義された識別子は、別の#define 前処理指令では再定義されません。 と同じです。ドラフトCから

引用++標準N4582

16.3マクロ置換[cpp.replace]

1 2つの置換リストが同一である場合との両方で前処理トークンは同じ番号を持っている場合のみ、 並べ替え、スペル、および空白の区切り。すべての空白の区切りは同じと見なされます。オブジェクト状マクロとして定義さ

2識別子現在デFiはレーデ別#define前処理 ディレクティブは第ドのfi nitionは、オブジェクトのようなマクロドのfi nitionであることを条件とすることによって定義さFiと2つの置換リスト が同一であってもよく、そうでなければプログラムは病気であります形成された。同様に、現在機能として定義されている識別子は、別の#define前処理指令によって再定義することができます。ただし、第2の定義は、同じ数字と綴りのパラメータを持つ 関数のようなマクロ定義であり、2つの置換は リスト同じものでなければ、プログラムは不正な形式になります。

関連する問題