c - 为什么预处理器的这个输出看起来没有意义?

标签 c clang

抱歉,标题不好,希望我的解释更清楚。

我有以下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/

相关文章:

计算以 'A' 字母开头的单词数? - C

在apple darwin中创建GNU C环境

比较字符串与C中的整数

c++ - 为什么这个变量被标记为 "unused"?

c++ - Qt 不使用 C++14 标准库

c - 将 C 编译从 MinGW 移植到 VisualStudio(nmake)

c - 插入到链表中

c++ - gcc 和 clang 抛出 "no matching function call"但 msvc (cl) 编译并按预期工作

c++ - 为什么 "void operator delete(void* ptr, std::size_t size) noexcept;"没有在 gcc 4.9.0 中定义?

MacOS 上的 Python3、gcc 和 clang