ОБЗОР
#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); }