隐式声明函数usleep

ant*_*009 24 c usleep

gcc (GCC) 4.6.3
c89
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用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
Run Code Online (Sandbox Code Playgroud)

但不确定我对上述内容做了什么?

pax*_*blo 28

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

头文件本身只会定义usleep内部通常是一个庞大的#ifdef语句嵌套,开发人员花时间告诉你你需要做什么,这样你就不必花费数小时试图弄明白:-)

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

  • 声明_BSD_SOURCE; 要么
  • 声明其他三件事的复杂组合,我不打算解码.

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

#define _BSD_SOURCE
Run Code Online (Sandbox Code Playgroud)

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

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

  • 谢谢,有效。实际上,我必须在任何其他包含之前声明 _BSD_SOURCE。否则它一直给我同样的警告。我的glibc版本glibc-2.14.90-24.fc16.6.x86_64。 (2认同)
  • @paxdiablo 我的工具链抱怨`警告“_BSD_SOURCE 和_SVID_SOURCE 已弃用,使用_DEFAULT_SOURCE”`,所以我认为在某些情况下`_BSD_SOURCE` 不能解决问题 (2认同)
  • @PiotrKról如果您使用的是较新版本的glibc> 2.19,请添加`#define _DEFAULT_SOURCE`.如果您的代码可能使用旧版本和新版本的glibc构建`_BSD_SOURCE`.https://sourceware.org/glibc/wiki/Release/2.20#Packaging_Changes (2认同)

小智 19

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

例:

arm-linux-gcc -lpthread -std=gnu99  -o test ArmLinuxDataPipe1.2.1.c
Run Code Online (Sandbox Code Playgroud)

  • 这个!说-std = c99会收到警告。 (2认同)

Gab*_*les 7

For even better sleep demos in C now, see my eRCaGuy_hello_world repo, in these files, for example:

  1. sleep_nanosleep.c
  2. sleep_nanosleep_minimum_time_interval.c
  3. timinglib_sleep_and_sleep_until.c
  4. timinglib.h
  5. timinglib.c

nanosleep() demo: how to write your own sleep_us() function from nanosleep()

Add the following to the top of your code, with the #define _POSIX_C_SOURCE 199309L part coming before #include <time.h>, so that it will bring in the nanosleep() function from <time.h>!:

// This line **must** come **before** including <time.h> in order to bring in
// the POSIX functions such as `clock_gettime()`, `nanosleep()`, etc., from
// `<time.h>`!
#define _POSIX_C_SOURCE 199309L

// For `nanosleep()`:
#include <time.h>
Run Code Online (Sandbox Code Playgroud)

And then use nanosleep() instead, to create your own sleep_us() function to sleep a set number of microseconds:

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);
}
Run Code Online (Sandbox Code Playgroud)

For compiling and running on Linux Ubuntu, I created a sleep_test.c file and used:

gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_test
Run Code Online (Sandbox Code Playgroud)

References:

  1. (This is intentionally a circular reference: see my comments under this answer): Is there an alternative sleep function in C to milliseconds?
  2. http://man7.org/linux/man-pages/man2/nanosleep.2.html
    1. Mentions:

    _POSIX_C_SOURCE >= 199309L

Related:

  1. Another answer of mine which uses POSIX timing functions (ex: clock_gettime(): Get a timestamp in C in microseconds?

Going further:

  1. Try out clock_nanosleep() with a monotonic clock and flag TIMER_ABSTIME instead, to achieve something similar to FreeRTOS's vTaskDelayUntil() function, for precise and repeatable periodic actions.
    1. Increase the POSIX version by using #define _POSIX_C_SOURCE 200112L prior to #include <time.h> in order to get access to clock_nanosleep().


Dav*_*lor 5

Tl;博士

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

#define _XOPEN_SOURCE   600
#define _POSIX_C_SOURCE 200112L
Run Code Online (Sandbox Code Playgroud)

或者将编译器标志添加-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 标准,一个是成为 IEEE 标准的 POSIX,另一个是来自 Open Group (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,则不推荐使用。如果您选择任何选项,它们也会被启用,但这是一个坏主意。