【发布时间】:2016-02-16 04:08:46
【问题描述】:
这真的不应该是我必须问的问题,但不知何故,通过搜索回答我的问题,我什么也找不到。
为了再问一个问题,我做了三个文件:main.c、sub.c 和 sub.h。 main.c 有'main'函数,而 sub.c 只包含函数定义。
最初,main.c 将 '#include "sub.h"' 作为其唯一的包含语句。
尝试“gcc main.c -O3 -o test”会导致错误,指出函数 f()(在 sub.h 中声明,在 sub.c 中定义,并在 main.c 中引用)未被引用。 尝试“gcc main.c sub.c -O3 -o test”会导致预期的行为。
然后我修改了 test.c,删除了 #include 和对 f 的引用。 'gcc main.c -O3 -o test2' 按预期工作。
然后我重新添加了对 f 的引用,却忘记重新添加#include。尽管如此,“gcc main.c sub.c -O3 -o test3”仍按预期工作。
我注意到了这个错误,并故意将包含重新添加为“#include sub.c”。 'gcc main.c sub.c -O3 -o test4' 导致错误,说 f() 被定义了多次。 'gcc main.c -O3 -o test4 恢复正常工作。
我可以从中得出的唯一结论是,就本地文件而言,如果文件是源代码文件,则包含它并且不要将其添加到命令中,否则将其源代码添加到命令中并不要费心包含它,因为显然你是否包含它并不重要。我猜?
基本上,我的问题是,上述行为是否有意,如果是,是否记录在案,在哪里,以便我可以阅读它并就将来如何处理我的包含文件做出更明智的决定。
【问题讨论】:
-
一般来说,#include
.c文件是个坏主意。作为新手 C 程序员不要这样做。即使作为一个有经验的程序员,也没有多少情况下可以这样做。 -
@kaylum #include .c 文件始终是“有效的”,但很少是“必要的”。但是,“很少”不是“从不”。在我的特定情况下,包括 .c 文件允许编译器比 .h 文件优化得更好,并且还允许我轻松更改程序结构的一部分,尽管它在编译时保持不变,但在构建之间变化很大我的程序结构井井有条。
-
好的,然后回到你的问题。你到底在问什么? “本地包含的文件”是什么意思?您的意思是与源代码在同一目录中吗?如果是这样,就 gcc 而言,唯一的区别是它在哪里查找该文件。它不会改变编译或链接阶段。所以不清楚你在问什么。您的问题是您声明了两个
f副本。一次是通过 C 文件的包含获得的 main.c,一次是您显式链接的 C 文件本身。 -
明显有更多不同;如果我说,#include
,并使用在 stdlib.h 中声明的函数,那么它可以工作。当我#included "sub.h" 并使用在 sub.h 中声明的 f 时,它不起作用。我需要在命令起作用之前将 sub.c 添加到命令中,并且添加 sub.c 似乎否定了对#include 的需要。我的问题是,我在问题中描述的结果是否异常,或者是否符合预期,如果我想知道,我会读什么? -
你对编译过程的理解显然有些差距。
#include <stdlib.h>不能单独工作。它之所以有效,是因为编译器隐式链接到标准 C 库libc.so。后一步是您自己的sub.h示例中缺少的。在编译阶段,头文件 include 告诉 C 编译器“f 函数在某处定义,相信我”。在链接阶段,链接器需要找到实际定义。在标准库案例中,它位于 libc.so 中。在您的情况下,它在 sub.o 和 main.o 中都可以找到。