我刚刚完成了一项学校作业,我在测试我的代码时遇到了问题,因为在运行 make packetize
之后我不断得到以下输出(这是教授给我们的 makefile)
cc packetize.c -o packetize
/tmp/ccJJyqF6.o: In function `block_to_packet':
packetize.c:(.text+0xb1): undefined reference to `crc_message'
collect2: ld returned 1 exit status
make: *** [packetize] Error 1
block_to_packet
在名为 packetize.c
的文件中定义,crc_message
在 crc16.c
中定义(两者都包含 #include "data.h"
行)。 data.h
中也有crc_message
的函数标题 所有这些文件都在同一个目录中。在过去的一个半小时里,我一直在尝试编译它们,并且无休止地搜索谷歌,但无济于事。它与我读过的链接有关,我的导师没有教过这个,所以我不知道如何编译这些文件来测试它们的输出。谁能告诉我怎么了?
最佳答案
你的头文件绝对没问题。您遇到的是一个链接器错误:packetize.c
的编译运行没有问题,但是您正在尝试链接一个可执行文件文件 packetize
(因为您没有提供 -c
选项,该选项声明“编译为 object 文件”)。可执行文件还需要来自 crc16.c
的编译代码。
要么您必须在编译器行中提供所有源代码:
cc packetize.c crc16.c -o myApp
或者你必须编译成单独的目标文件,最终链接在一起:
cc -c packetize.c -o packetize.o
cc -c crc16.c -o crc16.o
cc packetize.o crc16.o -o myApp
前者是您在一次性命令行中执行的操作,后者是 Makefile 通常执行的操作。 (因为如果您所做的只是修改 packetize.c
,则不需要重新编译 crc16.c
。在大型项目中,重新编译可能会花费大量时间。)
编辑:
教程时间。注意给定命令行中是否存在 -c
选项。
考虑:
// foo.c
int foo()
{
return 42;
}
定义函数foo()
的源文件。
// foo.h
int foo();
头文件声明函数foo()
。
// main.c
#include "foo.h"
int main()
{
return foo();
}
源文件引用 foo()
。
在文件 main.c
中,include 使编译器知道,最终,在某处,将有函数 foo()
的定义,声明在 foo.h
。此时编译器只需要知道该函数将存在,它不接受任何参数,并且它返回 int
。这足以将源代码编译为目标代码:
cc -c main.c -o main.o
但是,它还不足以实际编译一个可执行文件:
cc main.c -o testproc # fail of compile-source-to-exe
ld main.o -o testproc # fail of link-object-to-exe
编译器被 promise (通过声明)foo()
的定义将存在,这对编译器来说已经足够了。
然而,链接器(在第一个示例中由 cc
隐式运行)需要该定义。可执行文件需要执行函数foo()
,但在main.c
中找不到它。无法解析对 foo()
的引用。 “ Unresolved 引用错误”。
您需要一次性编译两个源文件...
cc foo.c main.c -o testproc # compile-source-to-exe
...或编译 foo.c
并为链接器提供两个目标文件,以便它可以解析所有引用:
cc -c foo.c -o foo.o
ld foo.o main.o -o testproc # link-objects-to-exe
Post Scriptum:如上图所示直接调用 ld
很可能不会像那样工作。链接需要一些额外的参数,cc
隐式添加这些参数——C 运行时支持、标准 C 库,诸如此类。我没有在上面的例子中给出这些参数,因为它们会混淆问题并且超出了问题的范围。
关于c - 我的头文件有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21747762/