【问题标题】:Can -std=c99 prevent my #includes from working properly?-std=c99 可以阻止我的#includes 正常工作吗?
【发布时间】:2011-02-04 00:32:29
【问题描述】:

我正在尝试在 Linux 系统上编译 C 程序。我有stdlib.h#include 声明。

当我用gcc 编译程序如下:

gcc -std=c99 -g -o progfoo progfoo.c progbar.c

我收到有关 Implicit declaration of function [srand48, drand48, bzero, or close] 的警告。

编译为:

gcc -g -o progfoo progfoo.c progbar.c

没有给我警告,但它确实对我使用for 循环大喊大叫(这是首先添加-std=c99 的理由)。

鉴于man srand48 提到包括<stdlib.h>,我不确定还有什么问题。 for 循环对任何事情都不是必需的(它们只是为了节省初始化数组的时间)所以我可以毫无问题地删除它们,但在我这样做之前,我想确认 c99 标准是否正在取代一些我的#include 声明的一个方面。

我正在使用gcc 4.1.2-50 (Red Hat)

【问题讨论】:

    标签: c linux gcc


    【解决方案1】:

    -std=c99 会阻止我的#includes 正常工作吗?

    不,但它们可能会显示出您对它们如何工作的知识的限制:-)


    虽然函数[sd]rand48stdlib.h 中有一个原型,但它们在#ifdef 中,至少在我的系统上:

    #if defined __USE_SVID || defined __USE_XOPEN
    

    因此,您可能必须明确设置其中一个宏。

    但是,在您尝试之前,请注意它不起作用。那是因为所有这些东西都是由gccfeature test macros控制的。

    features.h 中有一组非常复杂的规则用于设置特定功能的开启或关闭,并且在那里创建的宏控制头文件包含和排除的内容。 __USE_* 变体将根据您提供的 other 宏被清除并设置在该头文件中。

    例如,要设置__USE_SVID 以便您可以使用srand48,您需要为编译器提供-D_SVID_SOURCE 参数。

    但也许更简单的方法是将 C99 与 GNU 扩展一起使用。为此,请将-std=c99 替换为-std=gnu99

    并且,对于bzeroclose,它们可以分别从strings.hunistd.h 获得。

    起初我有点困惑,为什么这些编译器与 -std=c99 编译时它们与 C99 完全没有,但后来我意识到该标志只控制 标准 C标题给你。

    strings.h(注意复数名称,这不是string.h)和unistd.h 都不是 ISO C 的一部分。

    【讨论】:

    • 好点,@Matteo,我倾向于将 macros 视为 事情的那些,例如 #define halfOf(x) ((x) / 2),而不仅仅是“标志”来控制编译。但是你是对的,我自己使用“变量”这个工作很容易导致与真实变量的混淆。所以我根据你的建议改变了它。
    • 对。知道当您在没有 -std= 标志的情况下进行编译时,您要求的是 -std=gnu89,它是 C89 加上 GNU 扩展 - 所以与此模式等效的 C99 是 -std=gnu99,这可能会有所帮助。
    • 最好学习如何以标准方式启用 POSIX 扩展,因为搞乱__USE_SVID__USE_XOPEN 本质上是不可移植的。它们可以在某些机器上工作(可能是 Linux-ish),但不能在其他机器上工作。使用-D_XOPEN_SOURCE=600-D_POSIX_C_SOURCE=200809L 更好 - 因此Kevin 的答案是更好的解决方案。
    • 通常情况下,我会同意,但是,由于标签特别说明了 Linux,而问题说明了 RedHat,我认为可移植性并不重要。
    【解决方案2】:

    看起来您使用的功能不是 ISO C99,所以当您请求 严格遵守 C99,它们将不可见。

    这里的信息:https://bugzilla.redhat.com/show_bug.cgi?id=130815

    -D_POSIX_C_SOURCE=200809L 标志应该可以工作。

    另请参阅此问题:Why can't gcc find the random() interface when -std=c99 is set?

    【讨论】:

    • 就像我必须在 HelloWorld.c 中为“printf”制作一个函数原型一样?我认为您不太了解我的问题。
    • 如果我理解正确,他会收到有关系统包含文件(stdlib.h)的警告,而不是在他自己的代码中。
    • 对不起,没有意识到这些函数不是自己写的,因为我只写过C99代码,没用过。编辑了我的答案。
    • -D_POSIX_C_SOURCE=200809L 是执行此操作的正确可移植方式。 -D_GNU_SOURCE 是 glibc 特有的。
    • 我对这个答案的唯一不满是我相信定义应该放在源文件本身(任何源文件中的第一件事),而不是命令行。毕竟,需要 POSIX 功能测试宏启用的功能的是源代码本身,而不是构建环境。否则,很好的答案。
    【解决方案3】:

    您遇到的错误听起来好像您正在使用的函数没有被声明。您确定为它们添加了正确的标题吗?

    另外,使用-std=c99 可能会禁用一些不属于标准的扩展。您提到的所有功能都不是 C 标准的一部分。如果你找不到单独的标题,你可以试试-std=gnu99

    【讨论】:

      【解决方案4】:

      -std=c99 导致标头省略任何可能与 C99 保留命名空间之外的名称使用冲突的内容,包括所有标准 POSIX 函数。请求标头为您提供 POSIX 接口的可移植方式是将 _POSIX_C_SOURCE 定义为与所需 POSIX 版本相对应的值。对于最新的 POSIX (2008),这意味着:

      #define _POSIX_C_SOURCE 200809L
      

      或在命令行上:

      -D_POSIX_C_SOURCE=200809L
      

      编辑:您想要的功能似乎不在 POSIX 基础中,而是在 XSI 选项中,因此您应该将 _XOPEN_SOURCE 定义为适当的值(700 是最新的)抓住他们。这也可以从命令行或您的源文件中完成(但如果从源文件中完成,则必须在之前包括任何系统头文件。

      【讨论】:

        【解决方案5】:

        C99 中不再允许隐式声明(假定未声明的函数返回 int)。

        也就是说,gcc 不会中止编译。

        尝试将strings.h 包含在bzero 中,另请参阅paxdiablo 的回答。

        【讨论】:

        • 我认为这就是正在发生的事情:实际上没有什么不同,但是如果没有 c99 的标准,就不会报告隐式函数定义。这意味着我的#includes 出于某种原因根本无法正常工作。地狱...
        【解决方案6】:

        您要求符合标准,而C99 没有将srand48() 定义为<stdlib.h> 提供的函数。

        对于 GNU C 库,您可以通过定义 /usr/include/features.h 顶部的注释中列出的一个或多个选项来请求附加功能,或者在 #include 之前通过 #define,或者使用 -D标记为gcc

        对于srand48()(和drand48()),您可能需要-D_XOPEN_SOURCE=500-D_SVID_SOURCE(或源文件中的#define _XOPEN_SOURCE 500 等)。

        bzero()close() 应该可以与 -std=c99 一起使用,如果您 #include 记录了它们的头文件,它们分别是 <strings.h><unistd.h>

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-06-30
          • 2014-07-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-14
          相关资源
          最近更新 更多