C 语言预定义宏
外观
简介[编辑 | 编辑源代码]
预定义宏是C语言标准规定的一系列由编译器实现的特殊宏,它们在预处理阶段被自动展开,提供编译环境、日期时间等系统级信息。这些宏的名称通常以双下划线开头和结尾(如__FILE__
),是调试和跨平台开发的重要工具。
标准预定义宏列表[编辑 | 编辑源代码]
以下是C99/C11标准中必须实现的宏:
宏名称 | 描述 | 示例展开值 |
---|---|---|
__DATE__ |
编译日期("Mmm dd yyyy"格式) | "Jun 15 2023" |
__TIME__ |
编译时间("hh:mm:ss"格式) | "14:30:45" |
__FILE__ |
当前源文件名(字符串字面量) | "example.c" |
__LINE__ |
当前行号(整型字面量) | 42 |
__STDC__ |
若编译器符合ANSI C标准则展开为1 | 1 |
__STDC_VERSION__ |
C标准版本(如199901L表示C99) | 201112L |
详细说明与示例[编辑 | 编辑源代码]
基础调试宏[编辑 | 编辑源代码]
最常用的调试组合是__FILE__
和__LINE__
:
#include <stdio.h>
int main() {
printf("Debug: %s line %d\n", __FILE__, __LINE__);
return 0;
}
输出示例:
Debug: test.c line 5
编译环境检测[编辑 | 编辑源代码]
通过__STDC__
系列宏可检测编译器合规性:
#if __STDC_VERSION__ >= 201112L
printf("Using C11 or later\n");
#elif __STDC_VERSION__ >= 199901L
printf("Using C99\n");
#else
printf("Using ANSI C (C89)\n");
#endif
特殊平台宏[编辑 | 编辑源代码]
不同编译器会扩展额外的预定义宏(非标准):
编译器 | 示例宏 | 用途 |
---|---|---|
GCC/Clang | __linux__ |
Linux平台检测 |
MSVC | _WIN32 |
Windows平台检测 |
通用 | __cplusplus |
C++模式检测 |
实际应用案例[编辑 | 编辑源代码]
调试日志系统[编辑 | 编辑源代码]
#define LOG(msg) \
fprintf(stderr, "[%s %s] %s:%d - %s\n", \
__DATE__, __TIME__, __FILE__, __LINE__, msg)
int main() {
LOG("Memory allocation failed");
return 0;
}
输出示例:
[Jun 15 2023 14:30:45] alloc.c:8 - Memory allocation failed
跨平台代码[编辑 | 编辑源代码]
#if defined(_WIN32)
#include <windows.h>
#define SLEEP(ms) Sleep(ms)
#elif defined(__unix__)
#include <unistd.h>
#define SLEEP(ms) usleep(ms * 1000)
#endif
高级用法[编辑 | 编辑源代码]
构建版本标识[编辑 | 编辑源代码]
结合多个宏生成唯一版本字符串:
#define STRINGIFY(x) #x
#define BUILD_VERSION "v1.0-" STRINGIFY(__DATE__)
// 展开结果示例:v1.0-Jun_15_2023
条件编译优化[编辑 | 编辑源代码]
使用__GNUC__
检测GCC特性:
#if __GNUC__ >= 5
// 使用GCC5+的特性
#define likely(x) __builtin_expect(!!(x), 1)
#else
#define likely(x) (x)
#endif
注意事项[编辑 | 编辑源代码]
- 预定义宏的值在预处理阶段确定,运行时不会改变
- 避免重定义标准预定义宏(如
#define __LINE__ 100
),这是未定义行为 - 平台特定宏需要查阅编译器文档
可视化关系[编辑 | 编辑源代码]
数学表示[编辑 | 编辑源代码]
在条件编译中,宏展开可视为函数:
页面模块:Message box/ambox.css没有内容。
预定义宏的展开结果可能因编译器而异,重要场景应进行充分测试。 |