Unistd.h и c99 в Linux
Этот простой .c файл:
#include <unistd.h>
void test() {
char string[40];
gethostname(string,40);
}
... при компиляции обычно работает нормально:
$ cc -Wall -c -o tmp.o tmp.c
$
... но когда скомпилирован в режиме C99, выдается предупреждение:
$ cc -Wall -std=c99 -c -o tmp.o tmp.c
tmp.c: In function `test':
tmp.c:5: warning: implicit declaration of function `gethostname'
$
Результирующий файл .o хорош, а ссылки работают. Я просто хотел бы избавиться от предупреждения. Я могу добиться этого в хакерском режиме, разместив объявления в моем собственном файле .h.
Что такое C99, что означает, что объявления в unistd.h не включаются?
Можно ли это преодолеть, не отказываясь от достоинства C99?
Я вижу ту же проблему для других стандартных библиотек.
Ответы
Ответ 1
Вам может потребоваться определить некоторые макросы в определенном порядке, чтобы получить прототип для gethostname()
От man gethostname
:
Требования к макросам для тестирования функций glibc (см. feature_test_macros (7)):
gethostname(): _BSD_SOURCE || _XOPEN_SOURCE >= 500
sethostname(): _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)
Итак:
#define _BSD_SOURCE
#include <unistd.h>
void test() {
char string[40];
gethostname(string,40);
}
Детали gory:
Если вы не укажете опцию -std-c99
, то features.h
(которая неявно включена в unistd.h
) по умолчанию будет устанавливать _BSD_SOURCE
таким образом, чтобы прототип для gethostname()
включался. Однако указание -std=c99
заставляет компилятор автоматически определять __STRICT_ANSI__
, что в свою очередь заставляет features.h
не определять _BSD_SOURCE
, если только вы не навязываете его своим собственным определением макроса функции (как указано выше).
Ответ 2
gethostname( )
не является стандартной функцией C (она не упоминается нигде в стандарте C99), поэтому при компиляции стандарту символ не задан.
Если вы используете инструментальную цепочку gcc
, используйте -std=gnu99
, и вы получите нужное поведение.
В качестве альтернативы, глядя на <features.h>
, вы можете использовать -D_GNU_SOURCE
или -D_XOPEN_SOURCE=500
для получения желаемого поведения.
Ответ 3
Прочтите man gethostname
. Он говорит в требованиях к макросам проверки функций, что _BSD_SOURCE
(или _XOPEN_SOURCE>500
) требуется для вытаскивания gethostname из unistd.h.
Далее прочитайте man feature_test_macros
. Вы обнаружите, что -std=c99
включается __STRICT_ANSI__
, который отключается _BSD_SOURCE
. Это означает, что вы не можете получить gethostname
из unistd.h
, если вы еще не определили _BSD_SOURCE
. Обычно я использую _GNU_SOURCE в моей командной строке (т.е. gcc -D_GNU_SOURCE -std=c99 file.c
) для большинства вещей, которая также включает _BSD_SOURCE
.
P.S. На странице руководства содержится примерная программа, которая может печатать текущие ft-макросы. Вы можете скомпилировать и запустить его для некоторых параметров компилятора.