这个C代码有什么问题?

时间:2012-08-22 04:56:30

标签: c header struct

我写了一个关于结构的示例程序。我写了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中的注释并仅编译它,它可以工作,但是当我如上所述闯入小块时它不起作用。

有什么不对?

3 个答案:

答案 0 :(得分:4)

您需要将所有 .c 文件一起编译,以便您可以使用 label.c catalog.c中定义的函数< / em>在 main.c

您可以使用gcc:

一步完成此操作
gcc main.c label.c catalog.c -o fish

这将编译每个单独的源文件并生成object files,它们将链接在一起以生成可执行文件。您正在查看的错误发生在链接阶段,当gcc尝试查找cataloglabel函数时。

答案 1 :(得分: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

答案 2 :(得分: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}${LDFLAGS}以及${LDLIBS}(或${LDLIBES})添加到链接行,但对于简单程序,我展示的内容就足够了。

您无需告诉make如何将main.c转换为main.o;它已经知道了。它将使用如下规则:

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

从匹配的.o文件创建.c文件。 (这是GNU Make notation; POSIX makemake的其他经典版本使用替代但松散等效的符号.c.o:代替%.o: %.c。)

如果您不介意每次都编译所有来源,您可以使用类似的规则:

SOURCES = main.c label.c catalog.c

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

这一次,${CFLAGS}几乎是强制性的(尽管你的裸机样本程序中没有它就会离开)。


请注意,make很挑剔; ${CC}行等命令行必须以 TAB 开头;空白不会。