为什么sys / stat.h不能用-std = c1x定义ino_t?

时间:2013-08-17 19:28:26

标签: c posix standards stat

我正在编写一些与我编写的C代码有关的奇怪问题。请考虑以下代码:

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

根据 POSIX.1-2008 ,头文件&lt; sys / stat.h &gt;定义ino_t 1

  

&lt; sys / stat.h&gt; 标头应定义blkcnt_tblksize_tdev_tino_t,{{1 }},mode_tnlink_tuid_tgid_toff_t类型,如&lt; sys / types.h&gt;

当我尝试在Linux系统上的文件 test.c 中编译源代码时会发生这种情况:

$ cat test.c
#include <sys/stat.h>
ino_t inode;
$ uname -srm
Linux 3.8.0-26-generic x86_64
$ lsb_release -d
Description:    Ubuntu 13.04
$ gcc -c test.c
$ gcc -std=c90 test.c
test.c:2:1: error: unknown type name 'ino_t'
$ gcc -std=c99 test.c     
test.c:2:1: error: unknown type name 'ino_t'
$ gcc -std=c1x test.c
test.c:2:1: error: unknown type name 'ino_t'

当我指定任何 -std 选项时,为什么time_t的定义不会显露出来?

2 个答案:

答案 0 :(得分:3)

我的fstat手册页也说明了sys/types.h,这解决了我的问题。 ino_tsys/stat.h的定义受功能宏__USE_XOPEN__USE_XOPEN2K保护。 sys/types.h中的定义不受此保护。

手册页也说包括unistd.h,但这不是解决问题所必需的。

根据feature_test_macros的手册页:

  

__STRICT_ANSI__                 ISO标准C.此宏由gcc(1)隐式定义                 例如,使用-std=c99-ansi标记进行调用。

我想这意味着任何XOPEN功能也都会被关闭。然而,我无法找到任何描述。

P.S。似乎R ..(见下文)认为这也在feature_test_macros的手册页中有所描述,但是我的有限的大脑无法找到确切的措辞,所以我想把它留作练习给读者。如果它在任何地方被描述,那么我希望它确实在那个手册页中。

请注意这个答案的要点如下:

  

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

答案 1 :(得分:0)

如果您使用-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

$ cc -std=gnu11 -fsyntax-only test.c ; echo $?
0

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

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

    应用程序命名空间中的
  1. System-specific predefined macros-std=cXX模式下被禁用。这是一件好事; application-namespace预定义的宏最好是confusing,最坏的情况是破坏合法代码。但是,众所周知,要破坏仍在寻找这些宏的系统头文件。

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

  3. -std=cXX模式下,GNU libc将尝试最小化其标题中可见的指定C标准之外和之外的扩展数。 (注意:GCC可以使用的许多其他C库将执行此操作。)如果sys/stat.h这样的标题不属于C标准,则采用此方法表示“仅显示我们支持的此标题的最旧版本中存在的功能”,这通常是非常古老和有限的,如POSIX.1-1993。这就是绊倒你的原因。您可以通过定义feature test macros来指导GNU libc以展示更新的POSIX等功能来解决它​​。

  4. 如果您是从头开始编写新的C程序,我建议您使用-Wall-Wpedantic(可能还有一堆其他-W switches),但我不< / em>建议使用-std=cXX,因为唯一的肯定效果是关闭系统特定的预定义,并且可能会破坏系统标头。通过试图找到_GNU_SOURCE_POSIX_C_SOURCE设置可以为您提供所需的一切(特别是如果您,或捆绑的第三方代码,可能会使用已弃用但仍然常见的函数,如_XOPEN_SOURCE)。