0

ここには 2 つのファイルがexterndemo1.cありexterndemo2.c、最初のファイルでは、arrファイル スコープで文字配列をexterndemo2.c宣言して初期化しexternましたdisplay()。そこから生じる私の混乱は次のとおりです。次の 3 つに答えてください。

 //File No.1--externdemo1.c

#include<stdio.h>
#include "externdemo2.c"

extern int display();
char arr[3]={'3','4','7'};
//extern char arr[3]={'3','4','7'};

//extern int main()
int main()
{
    printf("%d",display());
}


//File No.2--externdemo2.c

char arr[3];

int display()
{
    return sizeof(arr);
}

1)キーワード inarrなしで宣言したにもかかわらず、プログラムが正常にコンパイルされるのはなぜですか? 関数のデフォルトのリンケージが外部であることを読んだことがありますが、変数についてもそうであるかどうかはわかりません。グローバル変数にはストレージがあることしかわかりません。クラス。externexterndemo2.cextern

2)extern storage classとの厳密な違いは何ですか。これextern linkageについて明確にする必要があります。配列を定義した最初のファイルではarr、キーワードを使用していませんが、デフォルトでクラスexternがあることはわかっています。 2 番目のファイル、つまり、グローバル変数に関するextern storageデフォルトのストレージ クラスまたはリンケージはありませんか?externarrexterndemo2.c

3)最初のファイルのコメントアウトされた行を確認しますexterndemo1.c。テストするために、その行を使用しましたextern char arr[3]={'3','4','7'};が、エラーが発生します'arr' initialized and declared 'extern'。このエラーはどういう意味ですか?コメント行についても言及しましたextern int main()が、エラーや警告なしで正常に動作します。ではextern、関数がexternデフォルトであるのに、変数ではなく関数に使用できるのはなぜarrですか?

この件について私を救済するために、少し時間をください.それは、全体についての私の長引く疑問のほとんどをクリアします.3つのビット1)、2)、および3)externすべてに答えることができれば、それは大きな助けになるでしょう.Especially 3) is eating my brains out

4

3 に答える 3

2

主な質問

  1. 基本的に、のソースをexterndemo2.cファイルに含めているためですexterndemo1.c

  2. これが大きな問題です。初期化子がないため、 の行char arr[3];externdemo2.carray の暫定的な定義を生成しarrます。初期化を伴う実際の定義に遭遇すると、仮の定義はもはや仮の定義ではなくなりますが、重複した定義でもありません。

    extern storage classvsについてextern linkage...リンケージとは、シンボルが定義されているソースファイルの外からシンボルが見えるかどうかを指します。シンボル withextern linkageは、それが適切に宣言されている他のソース ファイルから名前でアクセスできます。定義されている限り、extern storage class「関数のスコープ外に格納される」ことを意味するため、どの関数にも依存しません。exern ストレージ クラスで定義された変数には、extern リンケージがある場合とない場合があります。

    キーワードstaticで定義されていないため、配列arrには extern リンケージがあります。これはグローバル変数です。

  3. コメントアウトされた行のコメントアウトを解除すると、1 つの配列に対して 2 つの定義ができますが、これは許可されていません。

プログラムを作成するためだけにコンパイルしなければならないことに気付きましexterndemo1.cた — コンパイラはコードをexterndemo2.c直接インクルードしているため、コードをインクルードしています。からオブジェクトファイルを作成できますexterndemo2.cexterndemo1.cただし、との両方のオブジェクト ファイルをリンクしてプログラムを作成することはできません。externdemo2.c関数の定義が複数になるからですdisplay()

補助的な質問

両方のファイルを [同じディレクトリ] に配置しました。最初のファイルに 2 番目のファイルを含めないと、最初のファイルをコンパイルするとエラーundefined referenceが表示されます。最初のファイルでその関数を使用externしたので、2 番目のファイルをインクルードしなくても、リンカはそれにリンクするはずではありませんか? または、リンカーはデフォルトのフォルダーでのみ検索しますか?

ここにはいくつかの混乱があります。1つずつ対処してみましょう。

リンキング

リンカー (通常はコンパイラによって起動される) は、コマンド ラインで指定されたオブジェクト ファイルとライブラリをリンクします。2 つのオブジェクト ファイルが必要な場合は、それらを呼び出してexterndemo1.objexterndemo2.objをリンクし、リンカーに (IDE のビルド システムを介して) 両方のオブジェクト ファイルを処理する必要があることを伝える必要があります。デフォルト。(標準 C ライブラリとプラットフォーム固有の拡張機能は通常、自動的に取得されます。ただし、それを止めるために何らかの手段を講じる必要はありません。)

リンカーは、参照を満たす可能性のある浮遊オブジェクト ファイルを探すのに時間を費やす義務はありません。実際、リンクするように指示されたオブジェクト ファイルとライブラリのみをリンクし、気まぐれに他のファイルを追加しないことが期待されます。ライブラリについてはいくつかの注意点があります (リンクするように指示されたライブラリの 1 つに他のライブラリへの参照が組み込まれている場合、リンカーはコマンド ラインに記載されていないライブラリを追加する可能性があります) が、リンカーは余分なオブジェクト ファイルを追加しません。ミックスに。

テンプレートのインスタンス化を伴う C++ は少し異なると主張されるかもしれませんが、実際にはほとんど同じ規則に従っています。

ソースコード

externdemo.h以下を含むヘッダー が必要です。

#ifndef EXTERNDEMO_H_INCLUDED
#define EXTERNDEMO_H_INCLUDED

extern int display(void);

extern char arr[3];  // Or extern char arr[]; -- but NOT extern char *arr;

#endif /* EXTERNDEMO_H_INCLUDED */

次に、ヘッダーを含めるようにソース ファイルを変更する必要があります。

//File No.1--externdemo1.c

#include <stdio.h>
#include "externdemo.h"

char arr[3] = { '3', '4', '7' };

int main(void)
{
    printf("%d\n", display());
    return 0;
}

と:

//File No.2--externdemo2.c

#include "externdemo.h"

int display(void)
{
    return sizeof(arr);
}

ここでの唯一のトリッキーな問題は、「externdemo2.cのサイズを本当に知っていarrますか?」ということです。答えは「はい」です (少なくとも Mac OS X 10.8.3 で GCC 4.7.1 を使用している場合)。ただし、ヘッダーの extern 宣言にサイズ ( extern char arr[];) が含まれていない場合、次のようなコンパイル エラーが発生します。

externdemo2.c: In function ‘display’:
externdemo2.c:7:18: error: invalid application of ‘sizeof’ to incomplete type ‘char[]’
externdemo2.c:8:1: warning: control reaches end of non-void function [-Wreturn-type]
于 2013-05-07T03:21:52.813 に答える
0

あなたのプログラムは少し間違っているようです。私には #include "externdemo2.c" 行が無効に見えます。

以下は私が行った修正であり、機能します。

    //File No.1--externdemo1.c

    #include <stdio.h>

    extern char arr[3];

    extern int display();

    int main()
    {
        printf("%d", arr[0]);
        printf("%d",display());
    }

    //File No.2--externdemo2.c


    char arr[3]={'3','4','7'};

    int display()
    {
        return sizeof(arr);
    }

理解を深めるために、以下のリンクに従ってください。

于 2013-05-07T03:24:03.340 に答える