我正在编写一些与我编写的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_t
,blksize_t
,dev_t
,ino_t
,{{1 }},mode_t
,nlink_t
,uid_t
,gid_t
和off_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
的定义不会显露出来?
答案 0 :(得分:3)
我的fstat
手册页也说明了sys/types.h
,这解决了我的问题。 ino_t
中sys/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
模式之间只有三个差异,其中两个通常不是您想要的:
System-specific predefined macros在-std=cXX
模式下被禁用。这是一件好事; application-namespace预定义的宏最好是confusing,最坏的情况是破坏合法代码。但是,众所周知,要破坏仍在寻找这些宏的系统头文件。
Trigraphs在-std=cXX
模式下启用,在-std=gnuXX
模式下禁用。你不想要三角形;它们在发明时已经过时了,而且很久以前它们应该已经从C标准中删除了。
在-std=cXX
模式下,GNU libc将尝试最小化其标题中可见的指定C标准之外和之外的扩展数。 (注意:GCC可以使用的许多其他C库将不执行此操作。)如果sys/stat.h
这样的标题不属于C标准,则采用此方法表示“仅显示我们支持的此标题的最旧版本中存在的功能”,这通常是非常古老和有限的,如POSIX.1-1993。这就是绊倒你的原因。您可以通过定义feature test macros来指导GNU libc以展示更新的POSIX等功能来解决它。
如果您是从头开始编写新的C程序,我建议您使用-Wall
和-Wpedantic
(可能还有一堆其他-W
switches),但我不< / em>建议使用-std=cXX
,因为唯一的肯定效果是关闭系统特定的预定义,并且可能会破坏系统标头。通过试图找到_GNU_SOURCE
或_POSIX_C_SOURCE
设置可以为您提供所需的一切(特别是如果您,或捆绑的第三方代码,可能会使用已弃用但仍然常见的函数,如_XOPEN_SOURCE
)。