FEATURE_TEST_MACROS - Linux手册页

时间:2019-08-20 18:01:53  来源:igfitidea点击:

Linux程序员手册 第7部分
更新日期: 2020-04-11

名称

feature_test_macros-功能测试宏

说明

功能测试宏允许程序员在编译程序时控制系统头文件公开的定义。

注意:为了有效,必须在包含任何头文件之前定义功能测试宏。这可以在编译命令(cc -DMACRO = value)中完成,也可以通过在包含任何标头之前在源代码中定义宏来完成。存在这样的要求:必须在包含任何头文件之前定义宏,因为头文件可以自由地相互包含。因此,例如,在以下几行中,定义_GNU_SOURCE宏可能无效,因为标头本身包括(POSIX明确允许这样做):

#include <abc.h>
#define _GNU_SOURCE
#include <xys.h>

通过防止暴露非标准定义,某些功能测试宏对于创建可移植应用程序很有用。其他宏可用于公开默认情况下不公开的非标准定义。

可以通过检查头文件来确定下面描述的每个功能测试宏的精确效果。注意:应用程序不需要直接包含;确实,我们不鼓励这样做。请参阅注释。

Specification of feature test macro requirements in manual pages

当函数需要定义功能测试宏时,"概要"手册页通常包含以下格式的注释(此示例来自acct(2)手册页):

#include <unistd.h>

int acct(const char *文件名);

Feature Test Macro Requirements for glibc (see
feature_test_macros(7)):

acct():_BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE

||表示为了从中获取acct(2)的声明,必须在包含任何头文件之前进行以下宏定义之一:

#define _BSD_SOURCE
#define _XOPEN_SOURCE        /* or any value < 500 */

另外,等效的定义可以包含在编译命令中:

cc -D_BSD_SOURCE
cc -D_XOPEN_SOURCE           # Or any value < 500

请注意,如下所述,默认情况下定义了一些功能测试宏,因此不一定总是需要明确指定摘要中显示的功能测试宏。

在某些情况下,手册页使用简写形式表达功能测试宏要求(此示例来自readahead(2)):

#define _GNU_SOURCE
#include <fcntl.h>

ssize_t readahead(int fd, off64_t *offset, size_t count);

在仅单个功能测试宏可用于公开函数声明且默认情况下未定义该宏的情况下,将使用此格式。

Feature test macros understood by glibc

以下各段说明了如何在Linux glibc 2.x,x> 0中处理功能测试宏。

首先,尽管总结了一些不耐烦的细节:

*
您最有可能需要在现代源代码中使用的宏是_POSIX_C_SOURCE(用于POSIX.1各种版本的定义),_ XOPEN_SOURCE(用于SUS的各种版本的定义),_ GNU_SOURCE(用于GNU和/或Linux特定的东西),和_DEFAULT_SOURCE(以获取通常默认情况下会提供的定义)。
*
某些宏定义为默认值。因此,尽管在手册页的提要中可能指示一个或多个宏是必需的,但可能不必显式定义它们。缺省值的完整详细信息在此手册页的后面提供。
*
定义_XOPEN_SOURCE的值为600或更大将产生与定义_POSIX_C_SOURCE的值为200112L或更大相同的效果。哪里看到
_POSIX_C_SOURCE >= 200112L
在手册页摘要中的功能测试宏要求中,以下内容具有相同的效果:
_XOPEN_SOURCE >= 600
*
定义_XOPEN_SOURCE的值等于或大于700的效果与定义_POSIX_C_SOURCE的值等于或等于200809L的效果相同。哪里看到
_POSIX_C_SOURCE >= 200809L
在手册页摘要中的功能测试宏要求中,以下内容具有相同的效果:
_XOPEN_SOURCE >= 700

Linux glibc理解以下功能测试宏:

__STRICT_ANSI__
ISO标准C。使用例如-std = c99或-ansi标志调用时,此宏由gcc(1)隐式定义。
_POSIX_C_SOURCE
Defining this macro causes header files to expose definitions as follows:
*
值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起)功能被公开(换句话说,等同于定义_ISOC99_SOURCE)。
*
(自glibc 2.10开始)值200809L或更高版本另外公开了与POSIX.1-2008基本规范相对应的定义(不包括XSI扩展名)。
_POSIX_SOURCE
使用任何值定义此过时的宏等效于使用值1定义_POSIX_C_SOURCE。
由于此宏已过时,因此在手册页中讨论功能测试宏要求时,通常不会记录其用法。
_XOPEN_SOURCE
Defining this macro causes header files to expose definitions as follows:
*
定义任何值都会暴露符合POSIX.1,POSIX.2和XPG4的定义。
*
大于等于500的值还会公开SUSv2(UNIX 98)的定义。
*
(自glibc 2.2起)值600或更大的值还公开了SUSv3的定义(UNIX 03;即POSIX.1-2001基本规范加上XSI扩展名)和C99定义。
*
(自glibc 2.10起)值700或更高将另外公开SUSv4的定义(即POSIX.1-2008基本规范以及XSI扩展名)。
If __STRICT_ANSI__

is not defined, or
_XOPEN_SOURCE

is defined with a value greater than or equal to 500
and

neither
_POSIX_SOURCE

nor
_POSIX_C_SOURCE

is explicitly defined, then
the following macros are implicitly defined:

*
_POSIX_SOURCE定义为值1。
*
_POSIX_C_SOURCE

is defined, according to the value of
_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(since glibc 2.10)
_POSIX_C_SOURCE定义为值200809L。
另外,将_XOPEN_SOURCE的值定义为500或更大将产生与定义_XOPEN_SOURCE_EXTENDED相同的效果。
_XOPEN_SOURCE_EXTENDED
如果定义了此宏,并且定义了_XOPEN_SOURCE,则公开与XPG4v2(SUSv1)UNIX扩展(UNIX 95)相对应的定义。用500或更大的值定义_XOPEN_SOURCE也会产生与定义_XOPEN_SOURCE_EXTENDED相同的效果。应该避免在新的源代码中使用_XOPEN_SOURCE_EXTENDED。
由于定义_XOPEN_SOURCE的值等于或大于500的效果与定义_XOPEN_SOURCE_EXTENDED的效果相同,因此后者的(过时的)功能测试宏通常不在手册页的摘要中描述。
_ISOC99_SOURCE(since glibc 2.1.3)
公开符合ISO C99标准的声明。
较早的glibc 2.1.x版本识别了一个等效的宏_ISOC9X_SOURCE(因为C99标准尚未最终定稿)。尽管已不再使用该宏,但glibc仍会继续使用该宏以实现向后兼容性。
定义_ISOC99_SOURCE还公开了ISO C(1990)修订1(" C95")定义。 (C95的主要变化是对国际字符集的支持。)
使用-std = c99选项调用C编译器会产生与定义此宏相同的效果。
_ISOC11_SOURCE(since glibc 2.16)
公开符合ISO C11标准的声明。定义此宏还可以启用C99和C95功能(如_ISOC99_SOURCE)。
使用选项-std = c11调用C编译器会产生与定义此宏相同的效果。
_LARGEFILE64_SOURCE
公开由LFS(大文件峰会)指定的替代API的定义,作为"单一UNIX规范"的"过渡扩展"。 (请参阅替代API,由一组带有名称后缀" 64"的新对象(即函数和类型)组成(例如,off64_t与off_tlseek64()与lseek()等)。新程序不应使用此宏;而应使用_FILE_OFFSET_BITS = 64。
_LARGEFILE_SOURCE
从历史上看,此宏用于公开某些函数(特别是fseeko(3)和ftello(3)),这些函数解决了使用long int进行文件偏移的早期API(fseek(3)和ftell(3))的局限性。如果_XOPEN_SOURCE的值大于或等于500,则隐式定义该宏。如前所述定义_XOPEN_SOURCE或使用值64定义_FILE_OFFSET_BITS是实现相同结果的首选机制。
_FILE_OFFSET_BITS
使用值64定义此宏会自动将对与文件I / O和文件系统操作相关的32位函数和数据类型的引用转换为对它们的64位副本的引用。这对于在32位系统上对大文件(>2 GB)执行I / O很有用。 (定义此宏将允许正确编写的程序使用大型文件,而无需重新编译。)
64位系统自然允许文件大小大于2 GB,在这些系统上,此宏无效。
_BSD_SOURCE(deprecated since glibc 2.20)
用任何值定义此宏都会导致头文件公开BSD派生的定义。
在包含2.18或更高版本的glibc版本中,定义该宏也会使BSD定义在某些标准冲突的情况下成为首选,除非_SVID_SOURCE_POSIX_SOURCE_POSIX_C_SOURCE_XOPEN_SOURCE,_XOPEN_SOURCE_EXTENDED中的一个或多个,或者在定义了B的情况下_GNU_SOURCE定义是不利的。从glibc 2.19开始,在发生冲突的情况下_BSD_SOURCE不再导致首选BSD定义。
从glibc 2.20开始,不建议使用此宏。现在,它的作用与定义_DEFAULT_SOURCE相同,但是会生成一个编译时警告(除非也定义了_DEFAULT_SOURCE)。请改用_DEFAULT_SOURCE。要允许需要glibc 2.19和更低版本中的_BSD_SOURCE以及glibc 2.20和更高版本中的_DEFAULT_SOURCE的代码在没有警告的情况下进行编译,请同时定义_BSD_SOURCE和_DEFAULT_SOURCE。
_SVID_SOURCE(deprecated since glibc 2.20)
使用任何值定义此宏都会导致头文件公开System V派生的定义。 (SVID == System V接口定义;请参阅standards(7)。)
从glibc 2.20开始,不建议使用与_BSD_SOURCE相同的方式来使用此宏。
_DEFAULT_SOURCE(since glibc 2.19)
可以定义该宏以确保即使在默认情况下将禁用默认设置时也提供"默认"定义,例如在显式定义单个宏或以其"标准"模式之一(例如,cc -std = c99)。定义_DEFAULT_SOURCE而不定义其他单个宏或以其"标准"模式之一调用编译器无效。
"默认"定义包括POSIX.1-2008和ISO C99所要求的定义,以及最初源自BSD和System V的各种定义。在glibc 2.19和更早的版本上,这些默认值近似等于显式定义以下内容:
cc -D_BSD_SOURCE-D_SVID_SOURCE-D_POSIX_C_SOURCE = 200809
_ATFILE_SOURCE(since 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(在2.10之前的glibc版本中的200112L在2.10之前的glibc版本中;在2001年2月发布的glibc版本中,200112L在glibc中是200109L;在2006年2月之前的glibc版本中,200112L在glibc中是200112L); 199506L值700(在2.10之前的glibc版本中为600;在2.2之前的glibc版本中为500)。此外,还公开了各种特定于GNU的扩展。
从glibc 2.19开始,定义_GNU_SOURCE也具有隐式定义_DEFAULT_SOURCE的作用。在2.20之前的glibc版本中,定义_GNU_SOURCE也具有隐式定义_BSD_SOURCE和_SVID_SOURCE的作用。
_REENTRANT
历史上,在各种C库上,必须在所有多线程代码中定义此宏。 (某些C库可能仍然需要这样做。)在glibc中,此宏还公开了某些可重入函数的定义。
但是,默认情况下,glibc多年来一直是线程安全的。从glibc 2.3开始,定义_REENTRANT的唯一作用是启用一个或两个相同的声明,这些声明也可以通过定义值为199606L或更大的_POSIX_C_SOURCE来启用。
_REENTRANT现在已过时。在glibc 2.25和更高版本中,定义_REENTRANT等效于使用值199606L定义_POSIX_C_SOURCE。如果通过任何其他方式(例如_POSIX_C_SOURCE本身,_XOPEN_SOURCE,_DEFAULT_SOURCE或_GNU_SOURCE)选择了更高的POSIX一致性级别,则定义_REENTRANT无效。
如果使用cc-pthread进行编译,则会自动定义此宏。
_THREAD_SAFE
(已弃用的)_REENTRANT的同义词,用于与某些其他实现兼容。
_FORTIFY_SOURCE(since 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)及其宽字符变体)。对于某些函数,将检查参数一致性。例如,当指定的标志包括O_CREAT时,检查open(2)是否提供了模式参数。并非所有问题都被检测到,只有一些常见情况。
如果_FORTIFY_SOURCE设置为1,且编译器优化级别为1(gcc -O1)及更高,则执行不应更改符合程序行为的检查。将_FORTIFY_SOURCE设置为2,将添加更多检查,但是某些符合要求的程序可能会失败。
某些检查可以在编译时执行(通过在头文件中实现的宏逻辑),并导致编译器警告。其他检查在运行时进行,如果检查失败,则会导致运行时错误。
从4.0版开始,使用此宏需要编译器支持,而gcc(1)则提供此支持。

Default definitions, implicit definitions, and combining definitions

如果未明确定义任何功能测试宏,则默认情况下定义以下功能测试宏:BSD_SOURCE(在glibc 2.19和更低版本中),SVID_SOURCE(在glibc 2.19和更低版本中),_ DEFAULT_SOURCE(自glibc 2.19起),_POSIX_SOURCE和_POSIX_C_S 200809L(2.10之前的glibc版本为200112L; 2.4之前的glibc版本为199506L; 2.1之前的glibc版本为199309L)。

如果STRICT_ANSI_ISOC99_SOURCE_POSIX_SOURCE_POSIX_C_SOURCE_XOPEN_SOURCE_XOPEN_SOURCE_EXTENDED_BSD_SOURCE(在glibc 2.19和更早版本中)或_SVID_SOURCE_和_SVID_SOURCE(在glibc中被定义)中,则没有显式地定义。

如果未明确定义_POSIX_SOURCE和_POSIX_C_SOURCE,并且未定义__STRICT_ANSI__或将_XOPEN_SOURCE定义为500或更大,则

*
_POSIX_SOURCE定义为值1;和
*
_POSIX_C_SOURCE

is defined with one of the following values:

*
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版本不了解_POSIX_C_SOURCE的值200112L和200809L,并且此宏的设置取决于glibc版本。
*
如果未定义_XOPEN_SOURCE,则_POSIX_C_SOURCE的设置取决于glibc版本:199506L,在2.4之前的glibc版本中; 200112L,在glibc 2.4至2.9中;和200809L,因为glibc 2.10。

可以定义多个宏。结果是累加的。

遵循规范

POSIX.1指定_POSIX_C_SOURCE,_POSIX_SOURCE和_XOPEN_SOURCE。

_XOPEN_SOURCE_EXTENDED由XPG4v2(也称为SUSv1)指定,但在SUSv2及更高版本中不存在。 _FILE_OFFSET_BITS没有任何标准指定,但是在其他一些实现中使用。

_BSD_SOURCE_SVID_SOURCE_DEFAULT_SOURCE_ATFILE_SOURCE_GNU_SOURCE_FORTIFY_SOURCE,_REENTRANT和_THREAD_SAFE特定于Linux(glibc)。

备注

是Linux / glibc专用的头文件。其他系统具有类似的文件,但通常使用不同的名称。该头文件会根据需要自动包含在其他头文件中:为了使用功能测试宏,无需显式包含它。

根据上面定义的功能测试宏中的哪个,在内部定义其他glibc头文件检查的各种其他宏。这些宏的名称以两个下划线作为前缀(例如__USE_MISC)。程序永远不要直接定义这些宏:相反,应该使用上面列表中的适当的功能测试宏。

示例

以下程序可用于探索如何根据glibc版本设置各种功能测试宏以及显式设置哪些功能测试宏。以下在具有glibc 2.10的系统上的shell会话显示了一些我们将看到的示例:

$ 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

Program source

/* 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);
}

另外参见

libc(7),标准(7)

info libc下的"功能测试宏"部分。

/usr/include/features.h

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/