15

私は#define声明に少し混乱しています。ライブラリでは、それらは多くの#ifdefsと#ifndefsを持つ異なるファイル間の通信手段のようです。

そうは言っても、私は2つのファイルfile1.cを持っており、内部file2.cで一緒にコンパイルされています。それでも、コンパイラ内で使用すると、次のエラーメッセージが表示されます。#define TEST 10file2.cTESTfile2.c

'TEST' undeclared (first use in this function)

#defineディレクティブはグローバルですか?

4

4 に答える 4

19

#definesはグローバルではなく、使用される場所での単なる置換です(同じコンパイル単位で宣言されている場合)

それらはグローバルではなく、シンボルではなく、リンケージには関係がなく、コンパイル前にのみ関係があります。

于 2012-05-09T09:02:02.160 に答える
11

#definedマクロは、通常のCスコープ規則に従わないという点でグローバルです。マクロからのテキスト置換は、マクロ名がその後に表示される場所#defineに(ほぼ)適用されます。(注目すべき例外は、マクロ名がコメントの一部または文字列リテラルの一部である場合です。)

ヘッダーファイルでマクロを定義すると、ファイルが後で明示的に定義を解除しない限り、そのヘッダーファイルであるすべて#includeのファイルがそのマクロを継承します(必要かどうかは関係ありません)#undef

あなたの例では、マクロfile2.cについて知りません。からTESTピックアップすることをどのように知るのでしょうか?魔法で?マクロはソースコードに対してテキスト置換を実行するため、生成されたオブジェクトファイルにはマクロの表現はありません。したがって、その置換ルール自体を知る必要があります。複数のファイル間でそれを共有する場合は、ファイルと共通のヘッダーファイルに存在する必要があります。#definefile1.cfile2.c#define.c#include

ライブラリに表示されるのがいくつ機能するかを具体的に尋ねる場合、それらの多くは、コンパイル環境によって提供される事前定義され#ifdefたマクロ名と照合している可能性があります。たとえば、C99コンパイラは、言語バージョンを指定するマクロを定義します。Microsoftコンパイラはマクロを定義します。(これらの定義済みマクロは、コンパイラー用に予約されているため、多くの場合、先頭の下線で始まります。)__STDC_VERSION___MSC_VER

さらに、ほとんどのコンパイラでは、コマンドライン引数として単純なマクロを定義できます。たとえば、を無効にするように定義された状態でgcc -DNDEBUG file1.cコンパイルするために、を介してコードをコンパイルできます。file.cNDEBUGassert

于 2012-05-09T09:26:22.407 に答える
1

誰かが後でこれを読んだ場合、そしていくつかの実用的な情報を追加する場合:

  • atmel、vs、iarなどの一部の環境では、グローバルな#defineディレクティブを定義できます。基本的に、これらの定義された値を何らかのコマンドライン形式でプリコンパイラに渡します。
  • バッチコマンドやmakefileなどでも同じことができます。
  • Arduinoは常にボードバリアント(通常はhardware \ arduino \ Variantsにあります)をすべてのコンパイルに追加します。その時点で、グローバル定義ディレクティブを含む新しいボードを作成し、そのように使用できます。たとえば、いくつかのデバッグディレクティブを含む元のmega2560からmega2560(debug)ボードを定義できます。テキストをコピーして貼り付け、適切に変更することで、「boards.txt」にそのバリアントへの参照を追加します。

結局のところ、そのグローバルhfileまたはグローバルディレクティブを何らかの方法でコンパイラに与える必要があります。

于 2017-09-12T13:59:22.367 に答える
0

file1.hを作成し、そこに定義を配置する必要があります。次にfile2.cで

#include "file1.h"

パイのように簡単:)

于 2012-05-09T09:29:13.370 に答える