feature_test_macros - макросы тестирования свойств
feature_test_macros(7)
макросы тестирования свойств
ОБЗОР
#include <features.h>
ОПИСАНИЕ
Макросы тестирования свойств позволяют программисту контролировать какие
определения будут доступны из системных заголовочных файлов при компиляции
программы.
ЗАМЕЧАНИЕ: В целях эффективности, макрос тестирования свойств должен
быть определён до включения всех заголовочных файлов. Это можно сделать или
в команде компиляции (cc -DМАКРОС=значение) или определив макрос в
исходном коде до включения заголовочных файлов.
Некоторые макросы тестирования свойств полезны для создания переносимых
приложений; они позволяют блокировать нестандартные определения. Другие
макросы можно использовать для разблокировки нестандартных определений,
которые по умолчанию недоступны. Влияние каждого макроса тестирования
свойств, описанного далее, можно узнать из содержимого заголовочного файла
<features.h>.
Обозначение макросов тестирования свойств в справочных страницах
Когда функции требуется определение макроса тестирования свойств в
ОБЗОРЕ
справочной страницы, обычно, содержится упоминание в следующем виде (этот
пример взят из справочной страницы acct(2)):
#include <unistd.h>
int acct(const char *filename);
Требования макроса тестирования свойств для glibc
(см. feature_test_macros(7)):
acct(): _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)
Символ || означает, что для получения объявления acct(2) из
<unistd.h> нужно определить любой из следующих макросов до
включения любых заголовочных файлов:
#define _BSD_SOURCE
#define _XOPEN_SOURCE /* или любое значение < 500 */
Или же эквивалентные определения могут быть включены следующей командой
компиляции:
cc -D_BSD_SOURCE
cc -D_XOPEN_SOURCE # или любое значение < 500
Как описывается далее, некоторые макросы тестирования свойств определяются
по умолчанию, поэтому макрос не всегда нужно указывать явно даже, если он
приведён в
ОБЗОРЕ.
В некоторых случаях в справочных страницах используется сокращённая запись
требований макросов тестирования свойств (пример из readahead(2)):
#define _GNU_SOURCE
#include <fcntl.h>
ssize_t readahead(int fd, off64_t *offset, size_t count);
Такой формат употребляется в случаях, когда достаточно одного макроса для
получения объявления функции, и этот макрос не определён по умолчанию.
Макросы тестирования свойств, распознаваемые glibc
В следующих параграфах описаны макросы тестирования свойств, управляющие
Linux glibc 2.
x, где
x > 0.
В Linux glibc распознаются следующие макросы тестирования свойств:
__STRICT_ANSI__
Стандарт ISO C. Этот макрос неявно определяется компилятором gcc(1), если
он вызывается с флагом -std=c99 или -ansi.
_POSIX_C_SOURCE
При определении этого макроса из заголовочных файлов становится доступно
следующее:
-
При значении 1 доступны определения, удовлетворяющие POSIX.1-1990 и ISO C
(1990).
-
При значении 2 и более дополнительно доступны определения, удовлетворяющие
POSIX.2-1992.
-
При значении 199309L и более дополнительно доступны определения,
удовлетворяющие POSIX.1b (расширения для реального времени).
-
При значении 199506L и более дополнительно доступны определения,
удовлетворяющие POSIX.1c (нити).
-
(начиная с glibc 2.3.3) При значении 200112L и более доступны определения,
удовлетворяющие базовой спецификации POSIX.1-2001 (за исключением расширения
XSI), а также свойства C95 (начиная с glibc 2.12) и C99 (начиная с glibc
2.10).
-
(начиная с glibc 2.10) При значении 200809L и более доступны определения,
удовлетворяющие базовой спецификации POSIX.1-2008 (за исключением расширения
XSI).
_POSIX_SOURCE
Определение этого устаревшего макроса с любым значением эквивалентно
определению _POSIX_C_SOURCE со значением 1.
_XOPEN_SOURCE
При определении этого макроса из заголовочных файлов становится доступно
следующее:
-
Определение с любым значением делает доступным определения, удовлетворяющие
POSIX.1, POSIX.2 и XPG4.
-
При значении 500 и более дополнительно доступны определения, удовлетворяющие
SUSv2 (UNIX 98).
-
(начиная с glibc 2.2) При значении 600L и более дополнительно доступны
определения, удовлетворяющие SUSv3 (UNIX 03; т. е., базовой спецификации
POSIX.1-2001 плюс расширение XSI), и определения C99.
-
(начиная с glibc 2.10) При значении 700 и более дополнительно доступны
определения, удовлетворяющие SUSv4 (т. е., базовой спецификации POSIX.1-2008
плюс расширение XSI).
If
__STRICT_ANSI__ не определено или определено
_XOPEN_SOURCE со
значением больше или равно 500
и явно не определено
_POSIX_SOURCE или
_POSIX_C_SOURCE, то неявно определяются следующие макросы:
•
_POSIX_SOURCE определяется со значением 1.
•
_POSIX_C_SOURCE определяется согласно значению
_XOPEN_SOURCE:
_XOPEN_SOURCE < 500
_POSIX_C_SOURCE определяется со значением 2.
500 <= _XOPEN_SOURCE < 600
_POSIX_C_SOURCE определяется со значением 199506L.
600 <= _XOPEN_SOURCE < 700
_POSIX_C_SOURCE определяется со значением 200112L.
700 <= _XOPEN_SOURCE (начиная с glibc 2.10)
_POSIX_C_SOURCE определяется со значением 200809L.
_XOPEN_SOURCE_EXTENDED
Если этот макрос определён вместе с _XOPEN_SOURCE, то доступны
определения, соответствующие расширениям UNIX (UNIX 95) XPG4v2
(SUSv1). Данный макрос также неявно определён, если определён
_XOPEN_SOURCE со значением 500 и более.
_ISOC99_SOURCE (начиная с glibc 2.1.3)
Делает доступными объявления, удовлетворяющие требованиям стандарта ISO C99.
Ранние версии glibc 2.1.x распознавали макрос-эквивалент _ISOC9X_SOURCE
(так как стандарт C99 ещё не был утверждён). Хотя использование последнего
макроса не рекомендуется, glibc пока поддерживает его для обратной
совместимости.
Делает доступными определения стандарта ISO C (1990) Amendment 1
(«C95»). Основным изменением в C95 была поддержка международных наборов
символов.
_ISOC11_SOURCE (начиная с glibc 2.16)
Делает доступными объявления, удовлетворяющие требованиям стандарта ISO
C11. Определение этого макроса также включает свойства C99 и C95 (подобно
_ISOC99_SOURCE).
_LARGEFILE64_SOURCE
Делает доступными объявления альтернативного программного интерфейса,
определяемого в LFS (Large File Summit) как «переходного расширение» на
Single UNIX Specification (смотрите
программный интерфейс состоит из набора новых объектов (т. е., функций и
типов), чьи имена оканчиваются на «»64 (например, off64_t и off_t,
lseek64() и lseek(), и т. д.). В новых программах не нужно указывать
этот макрос; вместо него указывайте _FILE_OFFSET_BITS=64.
_LARGEFILE_SOURCE
Данный макрос исторически используется для предоставления определённых
функций (в частности, fseeko(3) и ftello(3)), которые обходят адресные
ограничения раннего программного интерфейса (fseek(3) и ftell(3)), в
котором для файловых смещений использовался long int. Данный макрос
неявно определяется, если определён _XOPEN_SOURCE со значением больше или
равным 500. В новых программах не нужно определять данный макрос;
определение _XOPEN_SOURCE или _FILE_OFFSET_BITS со значением 64
является более предпочтительным механизмом для достижения того же
результата.
_FILE_OFFSET_BITS
При определении данного макроса со значением 64 ссылки на 32-битные функции
и типы данных, относящиеся к файловому вводу-выводу и операциям с файловой
системой, автоматически преобразуются в их 64-битные прототипы. Это полезно
для выполнения ввода-вывода в огромные файлы (> 2 гигабайт) на 32-битных
системах (определение данного макроса позволяет корректно написанным
программам использовать огромные файлы, для чего требуется только
перекомпиляция).
64-битные системы сразу позволяют работать с файлами размером больше 2
гигабайт, и на этих системах данный макрос ничего не делает.
_BSD_SOURCE (устарел начиная с glibc 2.20)
Определение данного макроса с любым значением приводит к доступности из
заголовочных файлов определений BSD.
В glibc до версии 2.18 включительно при определении данного макроса также
отдаётся приоритет определениям BSD в ситуациях, когда имеется конфликт со
стандартами. Если определён один из макросов _SVID_SOURCE,
_POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE,
_XOPEN_SOURCE_EXTENDED или _GNU_SOURCE, то определения BSD не
используются. Начиная с glibc 2.19 при наличии макроса _BSD_SOURCE
определения BSD в случае конфликта приоритета не имеют.
Начиная с glibc 2.20 этот макрос считается устаревшим. Теперь он действует
также как определение _DEFAULT_SOURCE, но при компиляции генерируется
предупреждение (если также не определён _DEFAULT_SOURCE). Используйте
_DEFAULT_SOURCE вместо него. Чтобы для кода, которому требуется
_BSD_SOURCE в glibc 2.19 и старее и _DEFAULT_SOURCE в glibc 2.20 и
новее, не выдавалось предупреждение при компиляции определите _BSD_SOURCE
и _DEFAULT_SOURCE одновременно.
_SVID_SOURCE (устарел начиная с glibc 2.20)
При определении этого макроса с любым значением из заголовочных файлов
становятся доступны определения System V (SVID == System V Interface
Definition; смотрите standards(7)).
Начиная с glibc 2.20 этот макрос устарел также как _BSD_SOURCE.
_DEFAULT_SOURCE (начиная с glibc 2.19)
Данный макрос можно определить, чтобы точно знать, что будут доступны
определения «по умолчанию» даже, если умолчательные макросы отключены, что
случается, когда отдельные макросы определяются явно, или компилятор
вызывается в одном из своих «стандартных» режимов (например, cc -std=c99). Определение _DEFAULT_SOURCE без определения отдельных
макросов или вызов компилятора в одном из его «стандартных» режимов не
работают.
Определения «по умолчанию» охватывают все, которые требуются POSIX.1-2008, а
также различные определения из BSD и System V. В glibc 2.19 и старее эти
значения по умолчанию приблизительно эквивалентны явному определению
следующего:
cc -D_BSD_SOURCE -D_SVID_SOURCE -D_POSIX_C_SOURCE=200809
_ATFILE_SOURCE (начиная с glibc 2.4)
При определении этого макроса с любым значением из заголовочных файлов
становятся доступны объявления набора функций с суффиксом «at»; смотрите
openat(2). Начиная с glibc 2.10 данный макрос также неявно определяется,
если определён _POSIX_C_SOURCE со значением 200809L или больше.
_GNU_SOURCE
При определении этого макроса (с любым значением) неявно определяются
_ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE,
_XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE со значением
200809L (200112L в версиях glibc до 2.10; 199506L в версиях glibc до 2.5;
199309L в версиях glibc до 2.1) и _XOPEN_SOURCE со значением 700 (600 в
версиях glibc до 2.10; 500 в версиях glibc до 2.2). Также становятся
доступны различные расширения GNU.
Начиная с glibc 2.19 определение _GNU_SOURCE также неявно определяет
_DEFAULT_SOURCE. В glibc до 2.20 версии определение _GNU_SOURCE также
неявно определяет _BSD_SOURCE и _SVID_SOURCE.
_REENTRANT
При определении этого макроса становятся доступны определённые
реентерабельные функции. Для многонитивых программ вместо него используйте
cc -pthread.
_THREAD_SAFE
Синоним _REENTRANT, предоставляется для совместимости с некоторыми
другими реализациями.
_FORTIFY_SOURCE (начиная с glibc 2.3.4)
Определение этого макроса вызывает выполнение нескольких простых проверок
для обнаружения ошибок переполнения буфера, которые возникают в различных
функциях работы со строками и памятью (например, memcpy(3), memset(3),
stpcpy(3), strcpy(3), strncpy(3), strcat(3), strncat(3),
sprintf(3), snprintf(3), vsprintf(3), vsnprintf(3), gets(3) и
их варианты для работы с широкими символами). Для некоторых функций
проверяется целостность аргумента; например, проверяется, что open(2)
передали в аргументе mode, если указан флаг O_CREAT. Обнаруживаются не
все проблемы, только самые распространённые.
Если значение _FORTIFY_SOURCE равно 1 и уровень оптимизации компиляции
равен 1 (gcc -O1) и больше, то выполняются проверки, которые не
изменяют поведение выверяемых программ. Если значение _FORTIFY_SOURCE
равно 2, то добавляются дополнительные проверки, но некоторые выверяемые
программы могут завершаться с ошибкой.
Некоторые проверки выполняются во время компиляции (через макросы,
реализованных в заголовочных файлах) и вызывают предупреждение компилятора;
другие проверки выполняются во время выполнения и приводят к ошибкам времени
выполнения.
Для работы этого макроса требуется поддержка в компиляторе, доступная в
gcc(1) начиная с версии 4.0.
Определения по умолчанию, неявные определения и объединяющие определения
Если макросы тестирования свойств не указаны явно, то по умолчанию действуют
следующие макросы тестирования свойств: _BSD_SOURCE (в glibc 2.19 и
старее), _SVID_SOURCE (в glibc 2.19 и старее), _DEFAULT_SOURCE
(начиная с glibc 2.19), _POSIX_SOURCE и _POSIX_C_SOURCE=200809L
(200112L в версиях glibc до 2.10; 199506L в версиях glibc до 2.4; 199309L в
версиях glibc до 2.1).
Если любой из макросов __STRICT_ANSI__, _ISOC99_SOURCE,
_POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE,
_XOPEN_SOURCE_EXTENDED, _BSD_SOURCE (в glibc 2.19 и старее) или
_SVID_SOURCE (в glibc 2.19 и старее) указан явно, то по умолчанию не
определяются макросы _BSD_SOURCE, _SVID_SOURCE и _DEFAULT_SOURCE.
Если макросы _POSIX_SOURCE и _POSIX_C_SOURCE не указаны явно и не
определён __STRICT_ANSI__ или _XOPEN_SOURCE определён со значением 500
или более, то
_POSIX_SOURCE определяется со значением 1; и
_POSIX_C_SOURCE определяется с одним из следующих значений:
-
2, если _XOPEN_SOURCE определён со значением меньше 500;
-
199506L, если _XOPEN_SOURCE определён со значением 500 или более, но
меньше 600; или
-
(начиная с glibc 2.4) 200112L, если _XOPEN_SOURCE определён со значением
600 или более, но меньше 700.
-
(начиная с glibc 2.10) 200809L, если _XOPEN_SOURCE определён со значением
700 или более.
-
Старые версии glibc не знают о значениях 200112L и 200809L у
_POSIX_C_SOURCE, и значение этого макроса зависит от версии glibc.
-
Если макрос _XOPEN_SOURCE не определён, то значение _POSIX_C_SOURCE
зависит от версии glibc: 199506L в версиях glibc до 2.4; 200112L в glibc от
2.4 до 2.9 и 200809L в glibc 2.10 и новее.
Можно определять несколько макросов; результат складывается.
СООТВЕТСТВИЕ СТАНДАРТАМ
В POSIX.1 описаны _POSIX_C_SOURCE, _POSIX_SOURCE и
_XOPEN_SOURCE. Макрос _XOPEN_SOURCE_EXTENDED указан в XPG4v2 (также
называемом SUSv1).
Макрос _FILE_OFFSET_BITS отсутствует в стандартах, но используется в
некоторых других реализациях.
Макросы _BSD_SOURCE, _SVID_SOURCE, _DEFAULT_SOURCE,
_ATFILE_SOURCE, _GNU_SOURCE, _FORTIFY_SOURCE, _REENTRANT и
_THREAD_SAFE есть только в Linux (glibc).
ЗАМЕЧАНИЯ
Файл <features.h> есть только в Linux/glibc. В других системах
есть аналогичный файл, но, обычно, с другим именем. Данный заголовочный
файл, если нужен, автоматически включается из других заголовочных файлов:
его необязательно явно указывать для использования макросов тестирования
свойств.
Согласно указанным макросам тестирования свойств раньше файла
<features.h>, внутри него определяются другие различные макросы,
которые проверяются в других заголовочных файлах glibc. Эти макросы имеют
имена, начинающиеся с двух подчёркиваний (например,
__USE_MISC). Программы никогда не должны определять эти макросы
самостоятельно: вместо этого нужно задействовать соответствующий макрос
тестирования свойств из перечисленных ранее.
ПРИМЕР
Представленную далее программу можно использовать для изучения какие
значения присваиваются макросам тестирования свойств в зависимости от версии
glibc и какие макросы тестирования свойств устанавливаются явно. В следующем
сеансе оболочки на системе с glibc 2.10 показаны несколько примеров того,
что мы увидели:
$ cc ftm.c
$ ./a.out
_POSIX_SOURCE defined
_POSIX_C_SOURCE defined: 200809L
_BSD_SOURCE defined
_SVID_SOURCE defined
_ATFILE_SOURCE defined
$ cc -D_XOPEN_SOURCE=500 ftm.c
$ ./a.out
_POSIX_SOURCE defined
_POSIX_C_SOURCE defined: 199506L
_XOPEN_SOURCE defined: 500
$ cc -D_GNU_SOURCE ftm.c
$ ./a.out
_POSIX_SOURCE defined
_POSIX_C_SOURCE defined: 200809L
_ISOC99_SOURCE defined
_XOPEN_SOURCE defined: 700
_XOPEN_SOURCE_EXTENDED defined
_LARGEFILE64_SOURCE defined
_BSD_SOURCE defined
_SVID_SOURCE defined
_ATFILE_SOURCE defined
_GNU_SOURCE defined
Исходный код программы
/* ftm.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
#ifdef _POSIX_SOURCE
printf("_POSIX_SOURCE defined\n");
#endif
#ifdef _POSIX_C_SOURCE
printf("_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE);
#endif
#ifdef _ISOC99_SOURCE
printf("_ISOC99_SOURCE defined\n");
#endif
#ifdef _ISOC11_SOURCE
printf("_ISOC11_SOURCE defined\n");
#endif
#ifdef _XOPEN_SOURCE
printf("_XOPEN_SOURCE defined: %d\n", _XOPEN_SOURCE);
#endif
#ifdef _XOPEN_SOURCE_EXTENDED
printf("_XOPEN_SOURCE_EXTENDED defined\n");
#endif
#ifdef _LARGEFILE64_SOURCE
printf("_LARGEFILE64_SOURCE defined\n");
#endif
#ifdef _FILE_OFFSET_BITS
printf("_FILE_OFFSET_BITS defined: %d\n", _FILE_OFFSET_BITS);
#endif
#ifdef _BSD_SOURCE
printf("_BSD_SOURCE defined\n");
#endif
#ifdef _SVID_SOURCE
printf("_SVID_SOURCE defined\n");
#endif
#ifdef _DEFAULT_SOURCE
printf("_DEFAULT_SOURCE defined\n");
#endif
#ifdef _ATFILE_SOURCE
printf("_ATFILE_SOURCE defined\n");
#endif
#ifdef _GNU_SOURCE
printf("_GNU_SOURCE defined\n");
#endif
#ifdef _REENTRANT
printf("_REENTRANT defined\n");
#endif
#ifdef _THREAD_SAFE
printf("_THREAD_SAFE defined\n");
#endif
#ifdef _FORTIFY_SOURCE
printf("_FORTIFY_SOURCE defined\n");
#endif
exit(EXIT_SUCCESS);
}