31
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

但不确定我与上述内容有什么关系?

4

6 回答 6

35

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

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

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

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

可能最简单的解决方法是简单地编译gcc -D _BSD_SOURCE或放置:

#define _BSD_SOURCE

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

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

于 2012-04-07T10:49:50.717 回答
20

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

例子:

arm-linux-gcc -lpthread -std=gnu99  -o test ArmLinuxDataPipe1.2.1.c
于 2013-04-07T12:11:11.010 回答
5

Tl;博士

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

#define _XOPEN_SOURCE   600
#define _POSIX_C_SOURCE 200112L

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

这告诉环境您的程序使用的是旧版本的 UNIX API,在该版本usleep()中未被弃用。

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

在 Linux 上,您_XOPEN_SOURCE可以_POSIX_C_SOURCE检查man feature_test_macros.

完整的图片

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

从历史上看,有几种不同的 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,则不推荐使用。如果您选择“随心所欲”选项,它们也会启用,但这是个坏主意。

于 2019-04-26T04:33:31.103 回答
3

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

// 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. (这是故意循环引用:请参阅我在此答案下的评论):C 中是否有替代睡眠函数到毫秒?
  2. http://man7.org/linux/man-pages/man2/nanosleep.2.html
于 2019-04-26T03:00:28.350 回答
2

问题答案:使用 #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

于 2020-04-13T20:31:06.053 回答
1

使用 nanosleep() 代替对我有用。

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

于 2018-10-05T02:21:54.330 回答