功能特性测试宏(Feature Test Macros)
C标准定义了一系列预定义宏,用于指示实现支持的C语言版本、环境类型以及可选特性支持情况。这些宏由编译器自动定义(无需包含头文件),常用于条件编译(#if、#ifdef 等),以确保代码在不同标准版本或实现间的可移植性。C23(ISO/IEC 9899:2024)中这些宏的核心定义未变,但新增了对新特性的版本检查支持。
这些宏在预处理阶段可用,通常无需显式包含头文件。
1. 核心预定义宏
__STDC__
值:通常 1(表示实现意图符合ISO C标准,可能包含扩展)。__STDC_VERSION__
值(长整型常量):- C90/C95:未定义或 199409L
- C99:199901L
- C11:201112L
- C17:201710L
- C23:202311L(实现支持C23时至少此值)
用于检查支持的C标准版本。
__STDC_HOSTED__
值:1(托管环境,提供完整标准库,如操作系统);0(自由站立环境,如裸机嵌入式,无标准库或部分库)。__STDC_MB_MIGHT_NEQ_WC__
值:1(表示多字节字符的编码可能与宽字符不同)。
2. 可选特性宏(C11及以后)
如果实现不支持相应可选特性,则定义这些宏为 1:
__STDC_NO_ATOMICS__:不支持原子操作(<stdatomic.h>)__STDC_NO_COMPLEX__:不支持复数类型(_Complex)__STDC_NO_THREADS__:不支持线程(<threads.h>)__STDC_NO_VLA__:不支持可变长度数组(VLA,C23已移除此特性,故现代实现通常定义此宏)
3. 其他相关宏
__STDC_ISO_10646__:表示wchar_t值遵循ISO/IEC 10646(Unicode)特定版本(如 201112L 表示2011年12月版)。__STDC_ANALYZABLE__、__STDC_LIB_EXT1__等(较少用,涉及界限检查函数等扩展)。
实现还可能定义编译器特定宏(如 __GNUC__、__clang__、__MSC_VER__),但这些非标准。
4. 用户定义特征测试宏
用户可在编译命令行(-D)或代码中定义某些宏,以请求特定扩展行为(非强制,但标准认可):
_POSIX_C_SOURCE:请求POSIX特性(值如 200809L)。_XOPEN_SOURCE:请求X/Open或UNIX特性。_GNU_SOURCE:请求GNU扩展。_ISOC11_SOURCE等(较少用)。
推荐优先检查 __STDC_VERSION__ 来适配标准特性。
使用示例
c
#include <stdio.h>
int main() {
#ifdef __STDC__
printf("符合 ISO C 标准\n");
#endif
#if defined(__STDC_VERSION__)
printf("C 标准版本: %ld\n", __STDC_VERSION__);
#endif
#if __STDC_VERSION__ >= 202311L
printf("支持 C23 特性\n");
#elif __STDC_VERSION__ >= 201710L
printf("支持 C17 特性\n");
#else
printf("较旧 C 标准\n");
#endif
#if __STDC_HOSTED__ == 1
printf("宿主环境\n");
#else
printf("独立环境\n");
#endif
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
可能的输出:
zsh - feature_test_macros
符合 ISO C 标准
C 标准版本: 202311L
支持 C23 特性
宿主环境
注意事项
- 这些宏是常量表达式,可用于
#if预处理。 - 在编写跨版本代码时,优先使用
__STDC_VERSION__检查新特性(如C23的typeof、constexpr等)。 - 实际值取决于编译器和编译选项(例如用
-std=c23启用C23模式)。 - 与头文件极限宏(如
<limits.h>、<float.h>)结合使用,可进一步增强代码可移植性。
这些特征测试宏是C语言可移植编程的核心工具。