0

実際、私は複数のファイルでコンパイルしていました。ファイルは次のとおりです。

ファイル main.c -->

#include <stdio.h>
void foo3(void)
{
        printf("INSIDE foo3 function\n");
}

int main()
{
        foo1();
        foo2();
        foo3();
}

ファイル 1.c -->

#include <stdio.h>
void foo1(void)
{
        printf("INSIDE foo1 function\n");
}

ファイル 2.c-->

#include <stdio.h>
void foo2(void)
{
        printf("INSIDE foo2 function\n");
}

今、次のようにgccを使用してコンパイルしました-->

gcc 1.c 2.c main.c -o main

以下は出力でした -->

INSIDE foo1 function
INSIDE foo2 function
INSIDE foo3 function

私の疑問は、どのようにmain() を呼び出すことができfoo1()foo2()いつそれらが で宣言されていないかmain.cです。foo3()しかし、次のように main.c を変更すると ( afterの定義を記述main())、次のようになります。

編集した main.c -->

#include <stdio.h>
int main()
{
        foo1();
        foo2();
        foo3();
}

void foo3(void)
{
        printf("INSIDE foo3 function\n");
}

そして、コンパイルすると、次のエラーが発生します。

main.c:9:6: warning: conflicting types for ‘foo3’ [enabled by default]
 void foo3(void)
      ^
main.c:6:2: note: previous implicit declaration of ‘foo3’ was here
  foo3();
  ^

foo1()と の場合に、このエラーが以前に表示されなかったのはなぜですかfoo2()。前もって感謝します。

4

1 に答える 1

1

私の疑問は、どのようにmain()呼び出すことができfoo1()foo2()いつそれらが宣言されていないかですmain.c

GCCコンパイラはデフォルトで古いANSI C (別名 C89) 言語を使用するため、宣言されていない関数が許可され、デフォルトで結果が返されますint

たとえば、コンパイラを起動してみてください

 gcc -std=c99 -Wall -g -c main.c

または (一度にすべてのファイルをコンパイルする場合)

 gcc -std=c99 -Wall -g 1.c 2.c main.c -o main

2014 年 9 月のGCC 4.9など、最近のGCCを使用する代わりに、リンク時のプロシージャ間の最適化を要求できます。gcc -fltogcc

これには、すべての関数を宣言するC99準拠のソース コードが必要です。-Wall(ほぼ) すべての警告を要求します。この-gオプションは、デバッグ可能なオブジェクト コード (またはすべてのファイルを一度にコンパイルする最後のコマンドの実行可能コード) を生成します。

編集しmain.cたときにfoo3 最初に出現したとき (内部main) が検出された場合、コンパイラはそれが を返す関数であると推測しますint。コンパイラがfoo3それの定義を見ると、当然文句を言います。

-Wstrict-prototypes警告オプションを使用できますgcc(ただし、-Wall常に使用することをお勧めします)。

リンク時には、C 関数の型 (および署名) は重要ではありません。リンカーは name を使用してジョブを実行します (ただし、C++ ではname manglingを使用します)。もちろん、間違った引数または結果で関数を呼び出すことは未定義の動作です。

従来の良い方法は、すべての使用済みおよびパブリックな関数と型 (および定数) を宣言する共通のヘッダー ファイルを用意し、そのヘッダー ファイルをソース ファイルに含めることです (これにより、これらの宣言を何度もコピー アンド ペーストする必要がなくなります)。myheader.hしたがって、次のような新しいヘッダーファイルが必要です

// file myheader.h
#ifndef MY_HEADER_INCLUDED
#define MY_HEADER_INCLUDED
void foo1(void);
void foo2(void);
void foo3(void);
#endif /*MY_HEADER_INCLUDED*/

#include "myheader.h"そして、すべてのソースファイルを追加します(#include <stdio.h>そこのディレクティブの後)。を使用したインクルード ガードトリックに注意してくださいMY_HEADER_INCLUDED

実際には、ヘッダー ファイルには通常、プログラムのAPIを説明するコメントが含まれています。

GNU makeについても学んでください。これにより、マルチソース コード ファイル プログラムの構築が容易になります (実行してコンパイルおよび構築するだけですmake)。のこれその例を参照してくださいMakefileC の前処理は、C コンパイルの最初のフェーズであることを理解してください。

于 2014-09-02T07:20:55.850 に答える