Feature Test Macros、C11与__USE_MISC相关编译问题咨询
关于GCC编译中
__USE_MISC、_DEFAULT_SOURCE与C11标准的疑问 问题背景
我有一段来自开源rdma-core包的代码(路径/tmp/prog.c):
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <endian.h> static inline __attribute__((deprecated)) uint64_t ntohll(uint64_t x) { return be64toh(x); } int main() { printf("Hello\n"); return 0; }
编译时遇到以下现象:
- 直接用
gcc /tmp/prog.c -o /tmp/prog -Wall编译完全正常 - 加上
-std=c11参数后(gcc /tmp/prog.c -o /tmp/prog -Wall -std=c11),编译器报错“be64toh函数隐式声明” - 额外添加
-D_DEFAULT_SOURCE参数后,编译又恢复正常
查看系统头文件endian.h发现,be64toh的定义被__USE_MISC宏控制,现在想搞清楚三个问题:
__USE_MISC的作用是什么?- 为什么
_DEFAULT_SOURCE会包含__USE_MISC,但C11标准却不包含? - 定义和不定义
_DEFAULT_SOURCE分别有什么影响?
注:已知ntohll函数已废弃,属于所用开源包的内容。
解答
1. __USE_MISC的作用
__USE_MISC是GNU C库(glibc)内部的宏,用来控制头文件中非标准、属于GNU扩展或BSD兼容层的函数/宏定义。这些内容不属于任何C语言标准(比如C11、C17),是glibc为兼容历史代码、提供额外实用功能而添加的。像be64toh这类字节序转换函数,最初是BSD系统的接口,glibc通过__USE_MISC把它们开放给用户。
2. 为何_DEFAULT_SOURCE包含它而C11标准不包含
- 当指定
-std=c11时,GCC会严格遵循C11标准的定义,只暴露标准里明确规定的函数和宏。be64toh不属于C11标准内容,所以头文件会屏蔽掉这些非标准接口,导致编译报错。 _DEFAULT_SOURCE是glibc定义的兼容性宏,作用是让编译器启用默认的、向后兼容的接口集,其中就包含__USE_MISC对应的非标准扩展。这个宏是为了让旧代码在新编译器版本下正常编译,不用逐个添加各种扩展宏(比如_BSD_SOURCE、_SVID_SOURCE),相当于glibc提供的“兼容模式开关”,把历史上常用的非标准接口全部打开。
3. 定义与不定义_DEFAULT_SOURCE的影响
- 定义
_DEFAULT_SOURCE:- 会启用glibc默认的兼容接口集,包括
__USE_MISC、__USE_XOPEN等宏对应的扩展内容,能访问很多非标准但实用的函数(比如be64toh、getline这类)。 - 好处是兼容性强,旧代码、依赖开源库的代码(比如rdma-core)更容易编译通过。
- 缺点是可能引入和标准C冲突的定义,或者使用到未来可能被移除的扩展接口。
- 会启用glibc默认的兼容接口集,包括
- 不定义
_DEFAULT_SOURCE(比如指定-std=c11且不添加该宏):- 编译器严格遵循指定的C标准,只暴露标准内的函数和宏,代码的可移植性更强(换其他符合C标准的编译器也能编译)。
- 但无法使用glibc特有的扩展接口,依赖这些接口的代码会出现“未声明”类的编译错误。
内容的提问来源于stack exchange,提问作者Yaakov Goldsmith
相关产品推荐
相关产品推荐

