Подтвердить что ты не робот

Неявное объявление функции usleep

gcc (GCC) 4.6.3
c89

Я пытаюсь использовать usleep. Однако я продолжаю получать следующее предупреждение:

неявное объявление функции usleep

Я включил заголовочный файл unistd.h.

В man-страницах упоминается что-то об этом. Но я не уверен, что понимаю:

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

Но не уверен, что мне делать с этим?

4b9b3361

Ответ 1

Этот список является предварительным условием для определения usleep. Это в основном C-подобное выражение, включающее переменные #define которое должно быть истинным перед включением заголовочного файла.

Сам заголовочный файл будет определять только usleep внутри того, что обычно является огромным гнездом операторов #ifdef и разработчики потратили время, чтобы рассказать вам, что вам нужно сделать, чтобы вам не пришлось тратить часы, пытаясь понять это самостоятельно. :-)

Предполагая, что вы используете glibc 2.12 или выше, это означает, что вы должны:

  • объявить _BSD_SOURCE; или же
  • объявить сложную комбинацию из трех других вещей, которые я не буду пытаться декодировать.

Вероятно, самое простое решение - просто скомпилировать с помощью gcc -D _BSD_SOURCE или поставить:

#define _BSD_SOURCE

в коде, прежде чем включить заголовочный файл, который дает вам usleep.

Возможно, вы захотите определить их перед любыми включениями в случае, если между различными заголовочными файлами есть зависимости.

Ответ 2

Это может сработать: добавьте -std=gnu99 при компиляции с gcc в Linux.

Пример:

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

Ответ 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 / 1e6;             // whole seconds
    ts.tv_nsec = (microseconds % 1e6) * 1e3;    // 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

Ответ 5

TL;DR

Если вам нужно получить устаревший код, который использует usleep() для компиляции, добавьте эти строки в заголовочный файл, который вы включаете перед любыми другими библиотеками:

#define _XOPEN_SOURCE   600
#define _POSIX_C_SOURCE 200112L

Или добавьте флаги компилятора -std=c11 -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L в ваш make файл.

Это говорит о том, что ваша программа использует эту старую версию UNIX API, в которой usleep() не устарела.

В качестве альтернативы - и если это новый код, безусловно, - замените usleep() на nanosleep(), установите макросы функционального теста в соответствии с вашей версией библиотеки и просмотрите свою кодовую базу на предмет других бит-гнилей.

В Linux вы можете проверить, какие значения _XOPEN_SOURCE и _POSIX_C_SOURCE поддерживает ваша библиотека в man feature_test_macros.

Полная картина

Более длинный ответ: вот что происходит.

Исторически существовало несколько различных стандартов UNIX, и в конечном итоге лучшая практика, которой пользовались все, заключалась в том, чтобы код указывал, для какой версии API UNIX он был написан. Программисты сделали это путем определения макроса функционального теста.

Одно из самых ранних разделений в UNIX было между AT & Ts System V и стандартным распределением Беркли (BSD) из Калифорнийского университета. Поскольку System V была официальной версией и ее поведение стало по умолчанию, тогда как BSD Unix был одним из самых ранних бесплатных программ и использовался во многих университетах, гораздо более распространено видеть, как устаревший код объявляет _BSD_SOURCE чем _SVID_SOURCE. Макрос _BSD_SOURCE частности, пытается включить расширения для различных операционных систем в течение более сорока лет. Иногда его даже используют как универсальное средство для нестандартных расширений. Оба макроса устарели, и в отличие от принятого в настоящее время ответа, вы никогда не должны использовать ни один из них в новом коде.

В этом столетии существовало два стандарта UNIX: POSIX, ставший стандартом IEEE, и спецификация Single Unix (SUS) от Open Group (X/Open). X/Open SUS - это расширенный набор POSIX и то, для чего вы обычно пишете. Раньше было несколько различных макросов тестирования функций, которые можно было объявить для включения текущих версий этих стандартов, и они все еще поддерживаются для обратной совместимости. Вы можете увидеть некоторые из них в условной вставке, но вам не нужно беспокоиться о них, когда вы пишете новый код. Один макрос, который проверяется кодом, _XOPEN_SOURCE_EXTENDED, теперь устарел, но исторически выбирал версию SUS с 1995 года.

Теоретически, правильным макросом проверки возможностей для установки в любой современной версии UNIX или Linux является _XOPEN_SOURCE. Вы должны найти самый последний номер версии, который поддерживает ваша библиотека. На практике, я думаю, что его разумное защитное кодирование также определяет _POSIX_C_SOURCE, чтобы гарантировать, что никто другой не сможет установить его непоследовательно и нарушить ваш код. Ваш вопрос является хорошим примером: если вы установите _XOPEN_SOURCE для обратной совместимости, но _POSIX_C_SOURCE будет установлен на более свежую версию в другом месте в вашей _POSIX_C_SOURCE инструментов, более высокая версия _POSIX_C_SOURCE будет иметь приоритет, и usleep() не будет работать.

Таким образом, эти условные usleep() означают, что usleep() не была функцией POSIX, но когда-то присутствовала на некоторых BSD-подобных ОС, и поэтому она вошла в SUS в 1995 году. Она устарела в 2008 году и выбрала любую версию. POSIX или SUS с тех пор активно отключает его. Следовательно, он включается, если вы выбираете версию 500 или 600 для SUS (и еще один устаревший синоним также включает его), но не рекомендуется, если вы выбираете любую последнюю версию POSIX или SUS. Они также включены, если вы выбираете вариант "все идет", но это плохая идея.