今天我不得不使用这个basename()功能,而man 3 basename(这里)给了我一些奇怪的信息:
笔记
有两个不同版本的basename() - 上面描述的POSIX版本,以及GNU版本,后者可以使用
#define _GNU_SOURCE
#include <string.h>
我想知道这#define _GNU_SOURCE意味着什么:它是否污染了我用GNU相关许可证编写的代码?或者它只是用于告诉编译器类似" 嗯,我知道,这组函数不是POSIX,因此不可移植,但我还是想用它 ".
如果是这样,为什么不给人们不同的标题,而不是必须定义一些模糊的宏来获得一个函数实现或另一个?
有些东西也让我感到困惑:编译器如何知道哪个函数实现与可执行文件链接?它也使用这个#define吗?
有人有一些指示可以给我吗?
R..*_*R.. 160
定义_GNU_SOURCE与许可证无关,与写入(非)可移植代码有关.如果你定义_GNU_SOURCE,你会得到:
mount,ifconfig等等.只要您了解这些内容,定义就不应该是一个问题_GNU_SOURCE,但您应该避免定义它,而是定义_POSIX_C_SOURCE=200809L或_XOPEN_SOURCE=700尽可能确保您的程序是可移植的.
特别是,_GNU_SOURCE你永远不应该使用的东西是上面的#2和#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 启用了大量的编译标志
让我再回答两点:
有些东西也让我感到困惑:编译器如何知道哪个函数实现与可执行文件链接?它也使用这个#define吗?
一种常见的方法是根据是否定义,有条件地将#define标识符basename分配给不同的名称_GNU_SOURCE.例如:
#ifdef _GNU_SOURCE
# define basename __basename_gnu
#else
# define basename __basename_nongnu
#endif
Run Code Online (Sandbox Code Playgroud)
现在,库只需要在这些名称下提供这两种行为.
如果是这样,为什么不给人们不同的标题,而不是必须定义一些模糊的环境变量来获得一个函数实现或另一个?
通常相同的标题在不同的Unix版本中具有略微不同的内容,因此没有单一的正确内容,例如,<string.h>- 有许多标准(xkcd).有一整套宏来挑选你最喜欢的宏,所以如果你的程序需要一个标准,那么库就会符合这个标准.
有关可以全部启用的确切详细信息_GNU_SOURCE,文档可以提供帮助。
从GNU文档中:
巨集:_GNU_SOURCE
如果定义此宏,则将包括所有内容:ISO C89,ISO C99,POSIX.1,POSIX.2,BSD,SVID,X / Open,LFS和GNU扩展。在POSIX.1与BSD冲突的情况下,POSIX定义优先。
从Linux手册页上的功能测试宏:
_GNU_SOURCE
定义此宏(具有任何值)会隐式定义_ATFILE_SOURCE,_LARGEFILE64_SOURCE,_ISOC99_SOURCE,_XOPEN_SOURCE_EXTENDED,_POSIX_SOURCE,_POSIX_C_SOURCE值200809L(在2.10 2.1之前的glibc版本中的200112L在glibc版本中;在2.09 2.1之前的glibc版本中是200109L;在1995年版本的glibc中是200106L); 199506L _XOPEN_SOURCE的值为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的作用。
注意:_GNU_SOURCE需要在包含头文件之前进行定义,以便相应的头启用功能。例如:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
...
Run Code Online (Sandbox Code Playgroud)
_GNU_SOURCE也可以使用-D标志启用每个编译:
$ gcc -D_GNU_SOURCE file.c
Run Code Online (Sandbox Code Playgroud)
(-D不是特定于_GNU_SOURCE宏,而是以这种方式定义任何宏)。