【问题标题】:Why won't sys/stat.h define ino_t with -std=c1x?为什么 sys/stat.h 不使用 -std=c1x 定义 ino_t?
【发布时间】:2013-08-19 23:54:09
【问题描述】:

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

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

根据POSIX.1-2008,头文件>定义了ino_t1

标头应定义blkcnt_tblksize_tdev_tino_tmode_tnlink_tuid_tgid_toff_ttime_t 类型如 中所述。

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

$猫测试.c #include 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_t 的定义不显示?

【问题讨论】:

    标签: c posix standards stat


    【解决方案1】:

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

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

    根据feature_test_macros的手册页:

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

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

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

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

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

    【讨论】:

    • 啊,太好了。我刚刚发现显然将 _POSIX_C_SOURCE 定义为 200809L 也可以解决问题。
    • @R.. 我需要更多提示,因为我仍然找不到。
    • @R.. 是的,这看起来与我的版本非常相似,除了我缺少的 ftm 程序。我放弃了,所以我把它作为一个挑战留给了读者。
    【解决方案2】:

    如果您使用-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 模式下禁用。你不想要三元组;它们在被发明时就已经过时了,而且 IMNSHO 早就应该从 C 标准中删除它们了。

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

    如果您正在从头开始编写新的 C 程序,我建议您使用 -Wall-Wpedantic(可能还有一堆其他 -W switches),但我确实推荐使用-std=cXX 的唯一积极效果是关闭系统特定的预定义,这可能会破坏系统标题。直接使用_GNU_SOURCE 或等效项几乎总是比尝试找到提供所需一切的_POSIX_C_SOURCE_XOPEN_SOURCE 设置更容易(特别是如果你或第三方代码你捆绑包,可能会使用已弃用但仍然常见的函数,例如 gettimeofday)。

    【讨论】:

      猜你喜欢
      • 2020-11-11
      • 1970-01-01
      • 1970-01-01
      • 2014-10-06
      • 2013-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-19
      相关资源
      最近更新 更多