2

構造体に関するサンプルプログラムを作成しました。3つのソースファイルと1つのヘッダーファイルを作成しました。これは、プログラムの完全なソースです。

main.c:

#include <stdio.h>
#include <stdlib.h>
#include "fish.h"

/*
struct fish
{
    const char *name;
    const char *species;
    int teeth;
    int age;
};
*/

/*
void catalog(struct fish f)
{
    printf("%s is a %s with %i teeth. He is %i.",
           f.name, f.species, f.teeth, f.age);
}


void label(struct fish f)
{
    printf("Name: %s\n", f.name);
    printf("Species: %s\n", f.species);
    printf("Teeth: %i\n", f.teeth);
    printf("Age: %i\n", f.age);
}
*/

int main()
{
    struct fish snappy = {"Snappy", "Piranha", 69, 4};
    catalog(snappy);
    label(snappy);

    return 0;
}

label.c:

#include "fish.h"

void label(struct fish f)
{
    printf("Name: %s\n", f.name);
    printf("Species: %s\n", f.species);
    printf("Teeth: %i\n", f.teeth);
    printf("Age: %i\n", f.age);
}

catalog.c:

#include "fish.h"

void catalog(struct fish f)
{
    printf("%s is a %s with %i teeth. He is %i.",
           f.name, f.species, f.teeth, f.age);
}

私もmakefileを書きました:

fish.o: main.c label.c catalog.c fish.h
    gcc -c main.c label.c catalog.c
fish: fish.o
    gcc fish.o -o fish

私はcmdでプログラムをコンパイルします:

make fish

それは言う:

gcc -c main.c label.c catalog.c
label.c: In function 'label':
label.c:5:5: warning: incompatible implicit declaration of built-in function 'printf'    [enabled by default]
catalog.c: In function 'catalog':
catalog.c:5:5: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
cc   fish.o   -o fish
cc.exe: error: fish.o: No such file or directory
cc.exe: fatal error: no input files
compilation terminated.
make: *** [fish] Error 1

main.cのコメントを削除してコンパイルすると、動作しますが、上記のように細かく分割すると動作しません。

何が問題なのですか?

4

3 に答える 3

4

label.cで定義された関数とmain.cのcatalog.cで定義された関数を使用できるように、すべての.cファイルを一緒にコンパイルする必要があります。

これは、gccを使用して1つのステップで実行できます。

gcc main.c label.c catalog.c -o fish

これにより、個々のソースファイルがコンパイルされ、オブジェクトファイルが生成されます。これらのファイルは、リンクされて実行可能ファイルを生成します。catalog表示されているエラーは、gccがandlabel関数を見つけようとしているリンクフェーズ中に発生します。

于 2012-08-22T04:58:36.263 に答える
3

gcc main.c -o fishコンパイルのみmain.cmain.cについて知りませんlabel.c。他の場所で定義されている「label」と呼ばれる関数を呼び出さなければならないことだけを知っています。次に、リンカは生成されたすべてのオブジェクトファイルを調べ、それらを単一の実行可能ファイルに「リンク」します。

gcc main.c -c
gcc label.c -c
gcc catalog.c -c
ld main.o label.o catalog.o -o fish

これは明示的なバージョンです

gcc main.c label.c catalog.c -o fish
于 2012-08-22T05:04:47.757 に答える
2

このリンクルール:

fish: fish.o
    gcc fish.o -o fish

fish単一のオブジェクトファイルfish.o(おそらくからコンパイルされたもの)からプログラムを構築するのに適していますfish.c

別のルールが必要です:

OBJECTS = main.o label.o catalog.o

fish: ${OBJECTS}
    ${CC} -o $@ ${OBJECTS}

必要に応じて、リンク行に${CFLAGS}and${LDFLAGS}および${LDLIBS}(または)を追加できますが、単純なプログラムの場合は、私が示したもので十分です。${LDLIBES}

makeに変換する方法をmain.c教える必要はありませんmain.o。それはすでにそれを知っています。次のようなルールを使用します。

%.o: %.c
    ${CC} -c ${CFLAGS} $<

.o一致するファイルからファイルを作成し.cます。(これはGNU Make表記です。POSIXmakeおよびその他のクラシックバージョンでmakeは、代わりに代替の、しかし大まかに同等の表記を使用.c.o:%.o: %.cます。)

毎回すべてのソースをコンパイルしてもかまわない場合は、同様のルールを使用できます。

SOURCES = main.c label.c catalog.c

fish: ${OBJECTS}
    ${CC} ${CFLAGS} -o $@ ${SOURCES}

今回${CFLAGS}は、実質的に必須です(ただし、必要最低限​​のサンプルプログラムではそれなしで逃げることができます)。


makeそれはうるさいことに注意してください。行などのコマンドラインは;${CC}で始まる必要があります。TAB空白はしません。

于 2012-08-22T05:31:10.333 に答える