对不起,标题不好,希望我的解释更清楚。

我有以下c程序:

clang_test.c

#include "clang_test2.c"
int main()
{
    somefunc();
    return 0;
}


clang_test2.c

int somefunc()
{
    return 5;
}


然后,我使用带有-E参数的clang对其进行编译,以查看预处理器的结果。

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;
}


因此,基于此观察结果,查看预处理器的输出以诊断与功能定义/声明相关的问题是否不可靠?
而且由于两个预处理器输出之间的唯一区别是该文本块:

# 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。您将需要一个原型来告诉编译器其类型:

int somefunc(void);

int main(void)
{
    somefunc();
    return 0;
}


请注意,您应该始终使用适当的原型。没有参数的函数应使用void参数列表声明。旧式的函数接口(例如带有arg列表()的函数)允许原型允许编译器检测多种错误。

另一方面,使用-E编译器的输出

clang.exe -std=c99 -pedantic-errors -E .\clang_test2.c .\clang_test.c


确实将两个文件串联起来并通过C预处理器发送它们。区别-编译为对象和喜欢副连接-解释了您看到的行为。

关于c - 为什么预处理器的此输出似乎没有意义?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58794868/

10-11 00:35