2

以下に 2 つのCコードを示しますが、それらがどのように機能するのかわかりません。

プログラム 1 :

#include<stdio.h>
#define s 10
fun() {
 #undef s
 #define s 20
}
int main(){
 printf("%d\n",s);
 fun();
 printf("%d\n",s);
 return 0;
}
Output: 20
        20

プログラム 2:

#include<stdio.h>
#define s 10
int main(){
 printf("%d\n",s);
 fun();
 printf("%d\n",s);
 return 0;
}
fun() {
 #undef s
 #define s 20
}
output: 10
        10

私が知っているのは、プリプロセッサが開始前に機能main()し、そのすべての変数を置き換えることです。ここでfun()は 1 つ後に呼び出されprintf()ますが、両方のプログラムが の位置を変更することによってどのように異なる値を出力しているのfun()でしょうか?

4

3 に答える 3

5

プリプロセッサはスコープを気にしません。ファイルを上から下に 1 行ずつ調べて、テキストを置換します。何かが変更#defineまたは変更された場合#undef、その行からファイルの最後まで有効になります (または別のプリプロセッサ ステートメントがそれをオーバーライドします)。

于 2013-08-14T04:26:54.953 に答える
3

プリプロセッサ ステートメントは実行できません。それらは...まあ、前処理されています。これは、コンパイラが最初の単一パスを実行し、すべての前処理定義を解決することを意味します。前処理定義が C 制御構造内にある場合、C 制御構造の意味に関係なく実行されます。つまり、プリプロセッサの観点からは、C コードはありません。テキストのみ (およびその他のプリプロセッサ ステートメント)。

あなたの場合、この最初のパスで:

#include<stdio.h>     // File stdio.h is included/copied
#define s 10          // Preprocessor symbol s is defined as 10
fun() {               // Copied literally
    #undef s          // Preprocessor symbol s is undefined
    #define s 20      // Preprocessor symbol s is defined as 20
}                     // Copied literally
int main(){           // Copied literally
   printf("%d\n",s);  // Copied with s substituted, ie. printf("%d\n",20);
   fun();             // Copied literally
   printf("%d\n",s);  // Copied with s substituted, ie. printf("%d\n",20);
   return 0;          // Copied literally
}                     // Copied literally

したがって、実際にコンパイルされる入力は次のとおりです。

// Empty line originally corresponding to #include
// Empty line originally corresponding to #define
fun() {
    // Empty line originally corresponding to #undef
    // Empty line originally corresponding to #define
}
int main(){
   printf("%d\n",20);
   fun();
   printf("%d\n",20);
   return 0;
}

特に、この関数にはC 命令が含まfunていないことに注意してください。前処理の前に、2 つの前処理命令が含まれていましたが、次のとおりです。

  • プロ処理したら消えた
  • funその時点では関数funやその他の C コードは存在しなかったため、実際には関数に属していませんでした。テキストとプリプロセッサ ステートメントのみ。

この作業は通常、C コンパイラによってサイレントかつ内部的に行われます。ただし、それらの多くには、前処理されたソース ファイルを保存するオプションがあります。上記のような結果が得られるはずです (ただし、#include<stdio.h>多くの空白行と、ここでは単一の空白行として合成されたいくつかの C コードに展開されます)。

2 番目のケースは、OP の演習として残されています。

于 2013-08-14T04:24:01.427 に答える