为什么赢了';t sys/stat.h用-std=c1x定义ino\u t?

为什么赢了';t sys/stat.h用-std=c1x定义ino\u t?,c,posix,standards,stat,C,Posix,Standards,Stat,我在写一些C代码时遇到了一个奇怪的问题。考虑下面的代码: #include <sys/stat.h> ino_t inode; 为什么当我指定任何-std选项时,ino\u t的定义没有被重新定义?我的fstat手册页面说也包括sys/types.h,这为我解决了问题。sys/stat.h中的ino\u t的定义受功能宏\uuuuuu USE\uxopen和\uuu USE\uxopen2k的保护。sys/types.h中的定义不受此保护 手册页面还说要包括unistd.h,但这并

我在写一些C代码时遇到了一个奇怪的问题。考虑下面的代码:

#include <sys/stat.h>
ino_t inode;

为什么当我指定任何-std选项时,
ino\u t
的定义没有被重新定义?

我的
fstat
手册页面说也包括
sys/types.h
,这为我解决了问题。
sys/stat.h
中的
ino\u t
的定义受功能宏
\uuuuuu USE\uxopen
\uuu USE\uxopen2k
的保护。
sys/types.h
中的定义不受此保护

手册页面还说要包括
unistd.h
,但这并不是解决问题的必要条件

根据
功能测试宏的手册页

\uuuu STRICT\uu ANSI\uuuuu
ISO标准C。当 例如,使用
-std=c99
-ansi
标志调用

我想这意味着任何XOPEN功能都会被关闭。然而,我找不到任何关于这一点的描述

另外,似乎是R。。(见下文)觉得这在
功能测试宏的手册页中也有描述,但我有限的大脑无法找到确切的措辞,所以我想把它作为练习留给读者。如果它被描述在任何地方,那么我希望它确实出现在手册页面上

请注意,此答案的要点如下:

您应包括手册页中提到的所有文件,而不是试图对可能不需要的文件进行反向工程


如果您使用的是
-std=gnuXX
而不是
-std=cXX
,那么您的程序就可以毫无怨言地编译了

$ cc -std=c11 -fsyntax-only test.c ; echo $?
test.c:2:1: error: unknown type name ‘ino_t’; did you mean ‘__ino_t’?
1
但是

许多人没有正确理解
-std=cXX
选项的效果。他们自己并没有告诉GCC严格遵守(例如,诊断GNU扩展的所有使用)。如果您希望严格遵守,还必须提供选项
-Wall-Wpedantic

-std=cXX
模式和相应的
-std=gnuXX
模式之间只有三个区别,其中两个通常不是您想要的:

  • -std=cXX
    模式下禁用应用程序命名空间中的。这是一件好事;应用程序命名空间预定义宏充其量是破坏合法代码,最坏的情况是破坏合法代码。但是,已知会破坏仍在查找这些宏的系统头文件

  • -std=cXX
    模式下启用,在
    -std=gnuXX
    模式下禁用。你不想要三角图;它们在发明时就已经过时了,而且很早以前就应该从C标准中删除

  • -std=cXX
    模式下,GNU libc将尝试最小化在其标头中可见的超过指定C标准的扩展数量。(注意:GCC可以使用的许多其他C库将而不是这样做。)对于不属于C标准的标题,如
    sys/stat.h
    ,这意味着“仅公开我们支持的最旧版本的标题中存在的功能”,这通常是非常古老和有限的,如POSIX.1-1993。这就是你被绊倒的原因。您可以通过定义引导GNULIBC公开较新的POSIX等特性来解决这个问题


  • 如果您是从头开始编写新的C程序,我建议您使用
    -Wall
    -Wpedantic
    (可能还有其他一些),但我不建议使用
    -std=cXX
    ,因为唯一的积极效果是关闭系统特定的预定义,这可能会破坏系统头。直接使用
    \u GNU\u SOURCE
    或等效源代码,几乎总是比尝试找到一个
    \u POSIX\u C\u SOURCE
    \u XOPEN\u SOURCE
    设置来提供您所需的一切更少的麻烦(特别是如果您或捆绑的第三方代码可能使用不推荐但仍然很常见的函数,如
    gettimeofday
    ).

    太好了。我刚刚发现,显然将_POSIX_C_SOURCE定义为200809L也能起作用。@R..我还需要一个提示,因为我仍然找不到它。@R..是的,它看起来与我的版本非常相似,除了我缺少的
    ftm
    程序。我放弃了,所以我把它留给读者作为一个挑战。
    $ cc -std=c11 -fsyntax-only test.c ; echo $?
    test.c:2:1: error: unknown type name ‘ino_t’; did you mean ‘__ino_t’?
    1
    
    $ cc -std=gnu11 -fsyntax-only test.c ; echo $?
    0