抱歉,标题不好,希望我的解释更清楚。
我有以下c
程序:
clang_test.c
#include "clang_test2.c"
int main()
{
somefunc();
return 0;
}
clang_test2.c
int somefunc()
{
return 5;
}
然后,我使用 clang 和 -E
参数对其进行编译,以便查看预处理器的结果。
clang.exe -std=c99 -pedantic-errors -E .\clang_test.c
预处理器输出是这样的:
# 1 ".\\clang_test.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 324 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 ".\\clang_test.c" 2
# 1 "./clang_test2.c" 1
int somefunc()
{
return 5;
}
# 3 ".\\clang_test.c" 2
int main()
{
somefunc();
return 0;
}
这按预期工作,如果我尝试在不使用 -E
的情况下定期编译它,则不会出现编译错误。
为了进行实验,我将 clang_test.c
修改为不 #include clang_test2.c
:
int main()
{
somefunc();
return 0;
}
然后我尝试使用以下方法进行编译:
clang.exe -std=c99 -pedantic-errors .\clang_test2.c .\clang_test.c
我收到一个编译器错误:
.\clang_test.c:13:2: error: implicit declaration of function 'somefunc' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
somefunc();
但是如果我查看预处理器的输出,它似乎应该可以工作,因为 somefunc()
仍然在使用它的 main
函数上方声明:
# 1 ".\\clang_test2.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 324 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 ".\\clang_test2.c" 2
int somefunc()
{
return 5;
}
# 1 ".\\clang_test.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 324 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 ".\\clang_test.c" 2
int main()
{
somefunc();
return 0;
}
因此,根据这一观察,通过查看预处理器的输出来诊断与函数定义/声明相关的问题是否不可靠? 而且,由于两个预处理器输出之间的唯一区别是以下文本 block :
# 1 ".\\clang_test.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 324 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 ".\\clang_test.c" 2
它可以做什么来阻止 somefunc()
被正确地转发声明?
最佳答案
线路
clang.exe -std=c99 -pedantic-errors .\clang_test2.c .\clang_test.c
不只是连接两个文件并编译它们。它将每个 C 文件分别编译为对象 (.o
) 文件,然后链接它们。您会收到错误,因为单独编译,
int main()
{
somefunc();
return 0;
}
未定义somefunc
。您需要一个原型(prototype)来告诉编译器其类型:
int somefunc(void);
int main(void)
{
somefunc();
return 0;
}
请注意,您应该自始至终使用正确的原型(prototype)。不带参数的函数应使用 void
参数列表进行声明。旧式函数接口(interface)(例如,带有参数列表 ()
)允许原型(prototype)允许编译器检测到多种错误。
另一方面,带有-E的编译器的输出
clang.exe -std=c99 -pedantic-errors -E .\clang_test2.c .\clang_test.c
确实连接两个文件并通过 C 预处理器发送它们。差异 - 编译为对象和喜欢副连接 - 解释了您所看到的行为。
关于c - 为什么预处理器的这个输出看起来没有意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58794868/