“#define _GNU_SOURCE”意味着什么?

时间:2011-04-07 13:51:32

标签: c posix gnu

今天我必须使用basename()功能,man 3 basenamehere)给了我一些奇怪的信息:

  

备注

     

有两种不同版本的 basename() - 上面描述的 POSIX 版本,以及 GNU版本,其中一个版本< / p>      

#define _GNU_SOURCE
  #include <string.h>

我想知道这个#define _GNU_SOURCE意味着什么:它是否污染我用GNU相关许可证编写的代码?或者它只是用于告诉编译器类似“嗯,我知道,这组函数不是POSIX,因此不可移植,但我还是想用它”。

如果是这样,为什么不给人们不同的标题,而不是必须定义一些不起眼的宏来获得一个函数实现或另一个?

有些东西也让我感到困惑:编译器如何知道哪个函数实现与可执行文件链接?它是否也使用此#define

有人有一些指示要给我吗?

4 个答案:

答案 0 :(得分:154)

定义_GNU_SOURCE与许可无关,而与编写(非)可移植代码有关。如果您定义_GNU_SOURCE,您将获得:

  1. 访问许多非标准GNU / Linux扩展函数
  2. 访问POSIX标准中省略的传统功能(通常有充分的理由,例如被更好的替代品替换,或者与特定的传统实现相关联)
  3. 访问无法移植的低级功能,但有时需要实现mountifconfig等系统实用程序。
  4. 许多POSIX指定函数的破坏行为,其中GNU人员不同意标准委员会关于函数应该如何表现并决定做自己的事情。
  5. 只要您了解这些内容,定义_GNU_SOURCE应该不会有问题,但您应该避免定义它,而是尽可能定义_POSIX_C_SOURCE=200809L_XOPEN_SOURCE=700确保您的程序可移植。

    特别是,您应该永远不会使用_GNU_SOURCE的内容是#2和#4。

答案 1 :(得分:6)

让我再回答两点:

  

有些东西也让我感到困惑:编译器如何知道哪个函数实现与可执行文件链接?它也使用这个#define吗?

一种常见的方法是根据是否定义#define来有条件地basename标识_GNU_SOURCE到不同的名称。例如:

#ifdef _GNU_SOURCE
# define basename __basename_gnu
#else
# define basename __basename_nongnu
#endif

现在,图书馆只需要提供这些名称下的两种行为。

  

如果是这样,为什么不给人们不同的标题,而不是必须定义一些模糊的环境变量来获得一个函数实现或另一个?

相同的标题通常在不同的Unix版本中具有略微不同的内容,因此没有单一的正确内容,例如<string.h> - 有许多标准(xkcd)。 有一整套宏可以选择你最喜欢的宏,所以如果你的程序需要一个标准,那么库就会符合这个标准。

答案 2 :(得分:5)

有关_GNU_SOURCE所有功能的详细信息,文档可以提供帮助。

来自GNU文档:

  

宏:_GNU_SOURCE

     

如果定义此宏,则包含所有内容:ISO C89,ISO C99,POSIX.1,POSIX.2,BSD,SVID,X / Open,LFS和GNU扩展。在POSIX.1与BSD冲突的情况下,POSIX定义优先。

来自feature test macros上的Linux手册页:

  

_GNU_SOURCE

     

定义此宏(具有任何值)隐式定义                  _ATFILE_SOURCE,_LARGEFILE64_SOURCE,_ISOC99_SOURCE,                  _XOPEN_SOURCE_EXTENDED,_POSIX_SOURCE,_POSIX_C_SOURCE                  值200809L(200112L格式为2.10之前的glibc版本;                  199506L在glibc版本之前的2.5; 199309L in glibc ver-                  2.1)和_XOPEN_SOURCE之前的sions值为700(600                  在2.10之前的glibc版本中;之前的glibc版本有500个                  2.2)。此外,还有各种特定于GNU的扩展                  露出。

     

由于glibc 2.19,定义_GNU_SOURCE也具有效果                  隐式定义_DEFAULT_SOURCE。在glibc版本中                  在2.20之前,定义_GNU_SOURCE也有效果                  隐式定义_BSD_SOURCE和_SVID_SOURCE。

注意_GNU_SOURCE需要在之前定义,包括头文件,以便相应的标头启用这些功能。例如:

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
...
使用_GNU_SOURCE标志

,也可以在每次编译时启用

-D

$ gcc -D_GNU_SOURCE file.c

-D并非特定于_GNU_SOURCE,但任何宏都是以这种方式定义的。)

答案 3 :(得分:4)

通过谷歌的某些邮件列表:

  

看看glibc的include / features.h:

     

_GNU_SOURCE以上所有内容,以及GNU扩展。

     

这意味着它可以实现所有这些:

     

STRICT_ANSI ,_ ISOC99_SOURCE,_POSIX_SOURCE,_POSIX_C_SOURCE,   _XOPEN_SOURCE,_XOPEN_SOURCE_EXTENDED,_LARGEFILE_SOURCE,   _LARGEFILE64_SOURCE,_FILE_OFFSET_BITS = N,_BSD_SOURCE,_SVID_SOURCE

因此它为gcc

启用了大量的编译标志