C:头文件并包含问题。需要帮忙!

时间:2011-01-24 02:49:39

标签: c gcc makefile header-files

我的理解是C有makefile和include语句,所以你没有奇怪的怪物大小文件,你应该在功能上分解你的代码。因此,如果我是对的,我应该能够在.c文件之间进行函数调用,如果我做我的标题并且正确的话。

我正在尝试这样做,但不幸的是我收到了错误。

文件包含以下内容:

文件1)test.c:

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

main()
{
    printf("Hello World\n\n");
    printf("This is the number: %d \n\n", suc(6));
}

文件2)makefile:

CC=gcc
CFLAGS=-c -Wall

test: suc.o
$(CC) -Wall -o test test.c

suc.o: suc.c
$(CC) $(CFLAGS) suc.c

文件3)suc.h

#ifndef SUC_H_GUARD

#define SUC_H_GUARD

// returns the successor of i (i+1)
int suc(int i);


#endif

文件4)suc.c

#include "suc.h"

int suc(int i)
{
return i + 1;
}

当我制作(制作-B)顶部时,我得到:

gcc -c -Wall suc.c
gcc -Wall -o test test.c
test.c:7: warning: return type defaults to 'int'
/tmp/cc/7w7qCJ.o: In function 'main':
test.c: (.text+0x1d): undefined reference to 'suc'
collect2: ld returned 1 exit status
make: *** [test] Error 1

然而: 两者都产生预期的结果: A)这个单个文件程序工作正常!

#include<stdio.h>

main()
{
    printf("Hello World\n\n");
printf("This is the number: %d \n\n", suc(6));
}

int suc(int i)
{
return i + 1;
}

B)原始文件中的所有文件,但对test.c进行了以下更改:

#include<stdio.h>
#include"suc.h" //suc() is still defined b/c suc.h is included

main()
{
    printf("Hello World\n\n");
printf("This is the number: %d \n\n", 4); //HERE! -> no function call
}

请帮助,谢谢! 我不太明白错误消息试图告诉我的内容。

8 个答案:

答案 0 :(得分:4)

您需要将源文件单独编译为其目标文件,然后链接目标文件以获取可执行文件test

所以你需要:

CC=gcc
CFLAGS=-c -Wall

test: test.o suc.o
<tab>$(CC) -Wall -o test test.o suc.o

test.o: test.c
<tab>$(CC) $(CFLAGS) test.c

suc.o: suc.c
<tab>$(CC) $(CFLAGS) suc.c

其中<tab>是标签。


当前makefile中存在的问题是:

test: suc.o
    $(CC) -Wall -o test test.c

表示test取决于suc.o并获得test您需要执行的操作:

$(CC) -Wall -o test test.c

但是看看那个编译/链接行,它不包含任何定义了suc函数的源/目标文件。

您可以将suc.o添加为:

$(CC) -Wall -o test test.c suc.o

但是它被认为是不好的,因为你说你只更改suc.c文件然后你的makefile会重新生成suc.o并且还必须重新生成test,但是要重新生成test你正在重新编译test.c ,即使它没有被更改。

答案 1 :(得分:4)

在您的情况下,您将两个文件“suc.c”和“test.c”编译为两个不同的目标文件 - “suc.o”和“test.o”。但是,在链接程序时,只指定一个目标文件,这使链接器无法找到定义或“suc”函数。您必须将make文件更正为:

suc.o: suc.c
    $(CC) $(CFLAGS) suc.c

test.o: test.c
    $(CC) $(CFLAGS) test.c

test: suc.o test.o
    $(CC) -Wall -o test suc.o test.o
祝你好运!

答案 2 :(得分:2)

构建测试时,您没有链接suc.o

test.csuc.c编译到目标文件中,然后将它们链接到最终的test可执行文件中。

这个makefile应该可以工作(确保用规则中的制表符替换空格):

CC=gcc
CFLAGS=-c -Wall

.PHONY: all
all: test

test: test.o suc.o
    $(CC) -Wall test.o suc.o -o test

test.o: test.c
    $(CC) $(CFLAGS) test.c

suc.o: suc.c
    $(CC) $(CFLAGS) suc.c

答案 3 :(得分:2)

您需要告诉链接器将编译后的代码包含在suc.o中(在第一个编译步骤中生成),因为C 链接器非常愚蠢;它不知道魔术的功能实现。 (这种方式偶尔会有用!)

使用它进行编译的第二步应该有效:

gcc -Wall -o test test.c suc.o

答案 4 :(得分:2)

除了告诉您与“suc.o”链接的所有答案之外,警告return type defaults to 'int'告诉您,您忽略了为main()函数声明返回类型。

正确的定义如下:

int main(int argc, char *argv[])

答案 5 :(得分:1)

此依赖关系行失败:

test: suc.o
   $(CC) -Wall -o test test.c

因为你没有链接到suc.o(而且,顺便说一句,测试取决于suc.o和test.o)

你的行应该是:

test: test.o suc.o
   $(CC) -Wall -o test test.o suc.o

test.o : test.c
   $(CC) -c test.c

答案 6 :(得分:1)

gcc -c file.c 

file.c编译为目标文件file.o

gcc -o test test.c 

将编译并将test.c链接到可执行文件。

但是为了创建可执行文件,您需要链接所需的所有目标文件,在您的情况suc.o中,所以您必须编写

gcc -c test.c
gcc -c sic.c
gcc -o test test.o sic.o

gcc -o test test.c sic.c

答案 7 :(得分:0)

这里肯定有足够的答案。一个人不能伤害。 Make(通常)非常聪明。让它使用它对标准构建规则的了解,并将Makefile简化为单行:

test: test.o suc.o

不要费心给它简单的构建规则,因为它通常可以猜测它们。 (我正在考虑使用gnu make,但大多数(如果不是全部)版本都会做同样的事情。)

另外,作为旁注,请考虑重命名您的可执行文件。名称“test”是引起混淆的原因,因为无论何时尝试运行它,您都会意外地获得内置shell或/ bin / test。