C编译器是否区分用户代码和库代码中定义的类型?

时间:2013-03-10 20:58:43

标签: c systypes.h

#include <sys/types.h>
//Line 2: typedef unsigned int uint;
//Line 3: typedef unsigned int uint;
int main() {
    uint a;
    return 0;
}

鉴于上述C代码,它已成功编译,因为uint在<sys/types.h>中定义。尽管它没有标准化,但它还是为Sys V兼容而添加,在代码中进行了评论。

取消注释上面代码的第二行仍然会导致成功编译。据我了解,不允许重新定义一种类型,通过取消注释第二行和第三行来确认,这将导致一个编译错误。

为什么编译器足够聪明,知道uint是在标准库或用户代码中定义的? gcc和clang都表现出一致的行为。

编辑: 在这种情况下,链接不是游戏的一部分。该错误仅在编译时重现,即(-c选项)。

添加行号以减少混淆。

编辑:

  

取消注释上面代码的第二行仍然会导致成功编译。据我了解,不允许重新定义一种类型,通过取消注释第二行和第三行来确认,这将导致一个编译错误。

我不知道为什么写这篇文章。显然,取消注释第2行和第3行不会导致gcc的编译错误。 Clang给出了默认编译选项的错误要严格得多,可以通过传递一些参数进行调整。

Here描述了是否允许多个typedef,结果证明它非常复杂。无论如何只是试图避免重复的typedef。

2 个答案:

答案 0 :(得分:2)

重复声明在C中完全有效,因此如果您按照描述取消注释两行,则不会发现任何错误,与您所说的相反。

对名称进行两次不同的声明将是一个错误。

重复定义也是一个错误,但是typedef不是定义(尽管def),它是一个声明。

答案 1 :(得分:1)

标准库也是用户代码,通常由其他用户编写。

  

取消注释上面代码的第二行仍然会导致成功编译。由于我&gt;理解它不允许重新定义一种类型,通过取消注释第二行和第三行来确认,这将导致一次编译错误。

在我的gcc上它没有。 (4.5.3版)

  

为什么编译器足够聪明,知道uint是在标准库或用户代码中定义的? gcc和clang都表现出一致的行为。

编译器不知道用户代码与标准库中的用户代码之间的区别。虽然编译器可以区分标准库文件和用户代码,但我真的没有理由这样做。它看到的只是文本数据,它可以是lex / parse / codegen。