今天我必须使用basename()
功能,man 3 basename
(here)给了我一些奇怪的信息:
备注
有两种不同版本的 basename() - 上面描述的 POSIX 版本,以及 GNU版本,其中一个版本< / p>
#define _GNU_SOURCE
#include <string.h>
我想知道这个#define _GNU_SOURCE
意味着什么:它是否污染我用GNU相关许可证编写的代码?或者它只是用于告诉编译器类似“嗯,我知道,这组函数不是POSIX,因此不可移植,但我还是想用它”。
如果是这样,为什么不给人们不同的标题,而不是必须定义一些不起眼的宏来获得一个函数实现或另一个?
有些东西也让我感到困惑:编译器如何知道哪个函数实现与可执行文件链接?它是否也使用此#define
?
有人有一些指示要给我吗?
答案 0 :(得分:154)
定义_GNU_SOURCE
与许可无关,而与编写(非)可移植代码有关。如果您定义_GNU_SOURCE
,您将获得:
mount
,ifconfig
等系统实用程序。只要您了解这些内容,定义_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
启用了大量的编译标志