【问题标题】:implicit declaration of function usleep函数usleep的隐式声明
【发布时间】:2012-04-20 16:18:47
【问题描述】:
gcc (GCC) 4.6.3
c89

我正在尝试使用usleep。但是,我不断收到以下警告:

函数usleep的隐式声明

我已经包含了unistd.h 头文件。

手册页对此有所提及。但我不确定我是否理解它:

usleep():
   Since glibc 2.12:
       _BSD_SOURCE ||
           (_XOPEN_SOURCE >= 500 ||
               _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) &&
           !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
   Before glibc 2.12:
       _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED

但不确定我要如何处理上述问题?

【问题讨论】:

  • 您错过的建议可以在您复制上述文本的同一手册页中找到:POSIX.1-2001 declares this function obsolete; use nanosleep(2) instead. POSIX.1-2008 removes the specification of usleep(). 因此,您会看到使其难以访问的事实背后的意图。只是不要在新代码中使用它。

标签: c usleep


【解决方案1】:

该列表是定义usleep 的先决条件。它基本上是一个涉及 #define 变量的类 C 表达式,在包含头文件之前必须为真。

头文件本身只会在#ifdef 语句的大量嵌套中定义usleep,开发人员已经花时间告诉您需要做什么,这样您就不必花费数小时试图自己弄清楚:-)

假设您使用的是 glibc 2.12 或更高版本,这意味着您必须:

  • 声明_BSD_SOURCE;或
  • 声明一个其他三件事的复杂组合,我不会费心去解码。

可能最简单的解决方法是简单地使用gcc -D _BSD_SOURCE 编译或输入:

#define _BSD_SOURCE

在包含提供usleep 的头文件之前的代码中。

您可能希望在 any 包含之前定义这些,以防各种头文件之间存在依赖关系。

【讨论】:

  • 感谢工作。实际上,我必须在任何其他包含之前声明 _BSD_SOURCE。否则它一直给我同样的警告。我的 glibc 版本 glibc-2.14.90-24.fc16.6.x86_64.
  • @ant2009,是的,这很可能是因为标头之间可能存在依赖关系。我会将其添加到答案中。
  • @paxdiablo 我的工具链抱怨warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE",所以我认为在某些情况下_BSD_SOURCE 不能解决问题
  • @PiotrKról 如果您使用的是较新版本的 glibc > 2.19,然后添加 #define _DEFAULT_SOURCE。如果您的代码可能是使用新旧版本的 glibc 构建的,那么也可以定义 _BSD_SOURCEsourceware.org/glibc/wiki/Release/2.20#Packaging_Changes
  • 确认标准的方法是将_XOPEN_SOURCE设置为600,这将适用于遗留代码。对于需要在同一程序中使用更新接口的新代码,您可以将其重写为使用nanosleep()
【解决方案2】:

这可能有效:在 Linux 上使用 gcc 编译时添加 -std=gnu99

例子:

arm-linux-gcc -lpthread -std=gnu99  -o test ArmLinuxDataPipe1.2.1.c

【讨论】:

  • 这个!说 -std=c99 你会得到一个警告。
【解决方案3】:

Using nanosleep() instead worked for me.

在相关说明中:usleep() 自 POSIX-2008 以来已被删除,并且 建议使用 nanosleep() 代替。

【讨论】:

    【解决方案4】:

    将以下内容添加到代码顶部:

    // For `nanosleep()`:
    #include <time.h>
    
    #define __USE_POSIX199309
    #define _POSIX_C_SOURCE 199309L
    

    然后使用nanosleep() 代替,创建您自己的sleep_us() 函数以休眠设定的微秒数:

    void sleep_us(unsigned long microseconds)
    {
        struct timespec ts;
        ts.tv_sec = microseconds / 1000000ul;            // whole seconds
        ts.tv_nsec = (microseconds % 1000000ul) * 1000;  // remainder, in nanoseconds
        nanosleep(&ts, NULL);
    }
    

    为了在 Linux Ubuntu 上编译和运行,我创建了一个 sleep_test.c 文件并使用:

    gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_test
    

    参考资料:

    1. (这是有意的循环引用:请参阅此答案下的我的 cmets):Is there an alternative sleep function in C to milliseconds?
    2. http://man7.org/linux/man-pages/man2/nanosleep.2.html

    【讨论】:

      【解决方案5】:

      Tl;博士

      如果您需要获取使用 usleep() 进行编译的旧代码,请将这些行添加到您在任何其他库之前包含的头文件中:

      #define _XOPEN_SOURCE   600
      #define _POSIX_C_SOURCE 200112L
      

      或者将编译器标志 -std=c11 -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L 添加到您的 makefile。

      这告诉环境您的程序使用this older version of the UNIX API,其中usleep() 未被弃用。

      或者——如果这是新代码,肯定会——用nanosleep()替换usleep(),为您的库版本适当地设置功能测试宏,并检查您的代码库是否有其他位损坏。

      在 Linux 上,您可以在 man feature_test_macros 中检查您的库支持的 _XOPEN_SOURCE_POSIX_C_SOURCE 的值。

      完整的图片

      更长的答案:这就是发生的事情。

      历史上有几种不同的 UNIX 标准,最终每个人都想到的最佳实践是让代码指定它是为哪个版本的 UNIX API 编写的。程序员通过定义一个功能测试宏来做到这一点。

      UNIX 中最早的分裂之一是 AT&T 的 System V 和加州大学的伯克利标准发行版 (BSD)。由于 System V 是正式版本并且其行为成为默认设置,而 BSD Unix 是一些最早的免费软件并在许多大学中使用,因此看到遗留代码声明 _BSD_SOURCE_SVID_SOURCE 更常见。 _BSD_SOURCE 宏特别尝试在 40 多年的时间里启用来自各种不同操作系统的扩展。有时,它甚至被用作非标准扩展的包罗万象。这两个宏都已弃用,并且与当前接受的答案相反,您不应该在新代码中使用任何一个。

      在本世纪,有两个 UNIX 标准,POSIX 成为 IEEE 标准,以及来自开放组 (X/Open) 的单一 Unix 规范 (SUS)。 X/Open SU​​S 是 POSIX 的超集,也是您通常编写的内容。曾经有许多不同的功能测试宏,您可以声明它们以启用这些标准的当前版本,并且仍然支持这些宏以实现向后兼容性。您可以在粘贴的条件中看到其中一些,但在编写新代码时无需担心它们。代码检查的一个宏 _XOPEN_SOURCE_EXTENDED 现在已过时,但历史上选择了 1995 年的 SUS 版本。

      理论上,在任何现代版本的 UNIX 或 Linux 上设置的正确功能测试宏是 _XOPEN_SOURCE。您应该查找您的库支持的最新版本号。在实践中,我认为同时定义_POSIX_C_SOURCE 是一种谨慎的防御性编码,以保证没有其他人可以不一致地设置它并破坏你的代码。您的问题就是一个很好的例子:如果您将 _XOPEN_SOURCE 设置为向后兼容,但将 _POSIX_C_SOURCE 设置为工具链中其他位置的更新版本,则较高版本的 _POSIX_C_SOURCE 将优先,usleep() 不会工作。

      所以,这些条件的意思是 usleep() 不是一个 POSIX 函数,但曾经出现在一些类似 BSD 的操作系统上,因此它在 1995 年进入了 SUS。它在 2008 年被弃用,并且从那时起,选择任何版本的 POSIX 或 SUS 都会主动禁用它。因此,如果您选择 SUS 的 500 或 600 版本(并且另一个过时的同义词也将其打开),则启用它,但如果您选择任何最新版本的 POSIX 或 SUS,则不推荐使用。如果您选择随心所欲选项,它们也会启用,但这是个坏主意。

      【讨论】:

        【解决方案6】:

        回答问题: 采用 #define _BSD_SOURCE#define _GNU_SOURCE

        对于那些有错误的人

        warning: #warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE" [-Wcpp]
         # warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE"
           ^~~~~~~
        

        使用#define _BSD_SOURCE后尝试使用

        #define _GNU_SOURCE
        

        注意:在包含提供usleep() 的标头之前使用,即在包含unistd.h 之前使用

        【讨论】:

          猜你喜欢
          • 2021-01-20
          • 1970-01-01
          • 2014-06-28
          • 2022-01-16
          • 2011-10-05
          • 2013-10-28
          • 2019-07-16
          • 2017-07-16
          相关资源
          最近更新 更多