2

我正在编写的一些 C 代码遇到一个奇怪的问题。考虑以下代码:

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

根据POSIX.1-2008,头文件<sys/stat.h > 定义ino_t1

< sys/stat.h>标头应定义<sys/types.h>blkcnt_t中所述的、blksize_tdev_tino_tmode_tnlink_tuid_tgid_toff_ttime_t类型。

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

$猫测试.c
#include <sys/stat.h>
ino_t 索引节点;
$ unname -srm
Linux 3.8.0-26-通用 x86_64
$ lsb_release -d
说明:Ubuntu 13.04
$ gcc -c 测试.c
$ gcc -std=c90 test.c
test.c:2:1:错误:未知类型名称“ino_t”
$ gcc -std=c99 test.c     
test.c:2:1:错误:未知类型名称“ino_t”
$ gcc -std=c1x test.c
test.c:2:1:错误:未知类型名称“ino_t”

为什么在我指定任何-std选项时定义为ino_tnot revelead ?

4

2 回答 2

4

我的手册页fstat说还包括sys/types.h,这为我解决了问题。ino_tin的定义sys/stat.h受到功能宏__USE_XOPEN和的保护__USE_XOPEN2K。中的定义sys/types.h不受这种方式的保护。

手册页还说 include unistd.h,但这不是解决您的问题所必需的。

根据手册页feature_test_macros

__STRICT_ANSI__ ISO 标准 C。这个宏在调用时由 gcc(1) 隐式定义,例如,使用-std=c99or-ansi标志。

我想这意味着任何 XOPEN 功能也都被关闭了。但是,我找不到任何描述。

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

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

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

于 2013-08-17T20:16:07.160 回答
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. 应用程序命名空间中特定于系统的预定义宏-std=cXX模式下被禁用。这是一件好事;application-namespace 预定义的宏充其量是令人困惑的,而在最坏的情况下,它会破坏合法代码。但是,已知会破坏仍在寻找这些宏的系统头文件。

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

  3. -std=cXX模式下,GNU libc 将尝试最小化在其标头中可见的超出指定 C 标准的扩展数量。(注意:可以使用 GCC 的许多其他 C 库会这样做。)如果头文件sys/stat.h不是 C 标准的一部分,这意味着“仅公开存在于我们支持的此标头的最旧版本”,这通常是非常古老且有限的,例如 POSIX.1-1993。这就是让你绊倒的原因。您可以通过定义功能测试宏来指导 GNU libc 公开更新的 POSIX 等功能来解决它​​。

如果您正在从头开始编写新的 C 程序,我建议您使用-Walland -Wpedantic(可能还有一堆其他-W开关)但我建议使用-std=cXX,因为唯一的积极作用是关闭系统特定的预定义,并且这可能会破坏系统标题。_GNU_SOURCE与尝试找到一个_POSIX_C_SOURCE_XOPEN_SOURCE设置为您提供所需的一切(特别是如果您或您捆绑的第三方代码可能使用已弃用但仍然存在-commonplace 函数,如gettimeofday)。

于 2017-11-30T17:38:35.807 回答