You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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宏控制,现在想搞清楚三个问题:

  1. __USE_MISC的作用是什么?
  2. 为什么_DEFAULT_SOURCE会包含__USE_MISC,但C11标准却不包含?
  3. 定义和不定义_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冲突的定义,或者使用到未来可能被移除的扩展接口。
  • 不定义_DEFAULT_SOURCE(比如指定-std=c11且不添加该宏):
    • 编译器严格遵循指定的C标准,只暴露标准内的函数和宏,代码的可移植性更强(换其他符合C标准的编译器也能编译)。
    • 但无法使用glibc特有的扩展接口,依赖这些接口的代码会出现“未声明”类的编译错误。

内容的提问来源于stack exchange,提问作者Yaakov Goldsmith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 16:03:18