C语言预处理器高级技巧与实战

预处理器是C语言编译过程的第一步,掌握预处理器的高级技巧能够让代码更加灵活、可维护和高效。

1. 宏定义高级技巧

基本宏定义和函数式宏

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
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>

// 基本宏定义
#define PI 3.14159265359
#define MAX_SIZE 1000
#define VERSION "1.0.0"

// 函数式宏
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))
#define ABS(x) ((x) < 0 ? -(x) : (x))

// 多行宏定义
#define SWAP(type, a, b) do { \
type temp = (a); \
(a) = (b); \
(b) = temp; \
} while(0)

void basicMacros() {
printf("=== 基本宏定义示例 ===\n");

printf("PI = %.6f\n", PI);
printf("MAX_SIZE = %d\n", MAX_SIZE);
printf("VERSION = %s\n", VERSION);

int x = 10, y = 20;
printf("\n函数式宏测试:\n");
printf("MAX(%d, %d) = %d\n", x, y, MAX(x, y));
printf("MIN(%d, %d) = %d\n", x, y, MIN(x, y));
printf("SQUARE(%d) = %d\n", x, SQUARE(x));
printf("ABS(%d) = %d\n", -15, ABS(-15));

printf("\n交换前:x = %d, y = %d\n", x, y);
SWAP(int, x, y);
printf("交换后:x = %d, y = %d\n", x, y);
}

字符串化和连接操作符

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <stdio.h>

// 字符串化操作符 #
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)

// 连接操作符 ##
#define CONCAT(a, b) a##b
#define MAKE_FUNCTION(name) void func_##name() { \
printf("This is function: %s\n", #name); \
}

// 创建变量名
#define DECLARE_VAR(type, name) type var_##name

// 生成函数
MAKE_FUNCTION(test1)
MAKE_FUNCTION(test2)
MAKE_FUNCTION(debug)

void stringifyAndConcat() {
printf("\n=== 字符串化和连接操作符 ===\n");

// 字符串化测试
printf("STRINGIFY(Hello) = %s\n", STRINGIFY(Hello));
printf("STRINGIFY(123) = %s\n", STRINGIFY(123));
printf("TOSTRING(__LINE__) = %s\n", TOSTRING(__LINE__));

// 连接操作符测试
int CONCAT(num, 1) = 100;
int CONCAT(num, 2) = 200;
printf("num1 = %d, num2 = %d\n", num1, num2);

// 声明变量
DECLARE_VAR(int, counter) = 42;
DECLARE_VAR(float, ratio) = 3.14f;
printf("var_counter = %d, var_ratio = %.2f\n", var_counter, var_ratio);

// 调用生成的函数
func_test1();
func_test2();
func_debug();
}

可变参数宏

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>

// 可变参数宏(C99标准)
#define DEBUG_PRINT(fmt, ...) \
printf("[DEBUG %s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)

#define ERROR_PRINT(fmt, ...) \
fprintf(stderr, "[ERROR %s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)

// 日志级别宏
#define LOG_LEVEL_DEBUG 0
#define LOG_LEVEL_INFO 1
#define LOG_LEVEL_WARN 2
#define LOG_LEVEL_ERROR 3

#ifndef LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_INFO
#endif

#define LOG(level, fmt, ...) do { \
if (level >= LOG_LEVEL) { \
const char* level_str[] = {"DEBUG", "INFO", "WARN", "ERROR"}; \
printf("[%s] " fmt "\n", level_str[level], ##__VA_ARGS__); \
} \
} while(0)

// 便捷的日志宏
#define LOG_DEBUG(fmt, ...) LOG(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
#define LOG_INFO(fmt, ...) LOG(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG_WARN(fmt, ...) LOG(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...) LOG(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)

void variableMacros() {
printf("\n=== 可变参数宏 ===\n");

DEBUG_PRINT("这是一个调试信息");
DEBUG_PRINT("变量值:%d", 42);
DEBUG_PRINT("多个参数:%d, %s, %.2f", 100, "test", 3.14);

ERROR_PRINT("这是一个错误信息");
ERROR_PRINT("错误代码:%d", -1);

// 日志级别测试
LOG_DEBUG("这是调试信息");
LOG_INFO("程序启动");
LOG_WARN("这是警告信息");
LOG_ERROR("发生错误:%s", "文件未找到");
}

2. 条件编译

基本条件编译

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <stdio.h>

// 编译时配置
#define FEATURE_LOGGING 1
#define FEATURE_ENCRYPTION 0
#define DEBUG_MODE 1

// 平台检测
#ifdef _WIN32
#define PLATFORM "Windows"
#define PATH_SEPARATOR "\\"
#elif defined(__linux__)
#define PLATFORM "Linux"
#define PATH_SEPARATOR "/"
#elif defined(__APPLE__)
#define PLATFORM "macOS"
#define PATH_SEPARATOR "/"
#else
#define PLATFORM "Unknown"
#define PATH_SEPARATOR "/"
#endif

// 编译器检测
#ifdef __GNUC__
#define COMPILER "GCC"
#define COMPILER_VERSION __GNUC__
#elif defined(_MSC_VER)
#define COMPILER "MSVC"
#define COMPILER_VERSION _MSC_VER
#elif defined(__clang__)
#define COMPILER "Clang"
#define COMPILER_VERSION __clang_major__
#else
#define COMPILER "Unknown"
#define COMPILER_VERSION 0
#endif

void conditionalCompilation() {
printf("\n=== 条件编译示例 ===\n");

printf("平台:%s\n", PLATFORM);
printf("路径分隔符:%s\n", PATH_SEPARATOR);
printf("编译器:%s\n", COMPILER);
printf("编译器版本:%d\n", COMPILER_VERSION);

#if FEATURE_LOGGING
printf("日志功能已启用\n");
#else
printf("日志功能已禁用\n");
#endif

#if FEATURE_ENCRYPTION
printf("加密功能已启用\n");
#else
printf("加密功能已禁用\n");
#endif

#ifdef DEBUG_MODE
printf("调试模式已启用\n");
#if DEBUG_MODE > 0
printf("调试级别:%d\n", DEBUG_MODE);
#endif
#endif
}

版本控制和特性检测

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <stdio.h>

// 版本定义
#define VERSION_MAJOR 2
#define VERSION_MINOR 1
#define VERSION_PATCH 3
#define VERSION_BUILD 1234

// 版本比较宏
#define MAKE_VERSION(major, minor, patch) \
((major) * 10000 + (minor) * 100 + (patch))

#define CURRENT_VERSION MAKE_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH)

// 特性版本检查
#if CURRENT_VERSION >= MAKE_VERSION(2, 1, 0)
#define FEATURE_NEW_API 1
#else
#define FEATURE_NEW_API 0
#endif

#if CURRENT_VERSION >= MAKE_VERSION(2, 0, 0)
#define FEATURE_ADVANCED_LOGGING 1
#else
#define FEATURE_ADVANCED_LOGGING 0
#endif

// C标准检测
#if __STDC_VERSION__ >= 201112L
#define C_STANDARD "C11"
#define HAS_STATIC_ASSERT 1
#elif __STDC_VERSION__ >= 199901L
#define C_STANDARD "C99"
#define HAS_STATIC_ASSERT 0
#elif defined(__STDC__)
#define C_STANDARD "C90"
#define HAS_STATIC_ASSERT 0
#else
#define C_STANDARD "Pre-ANSI"
#define HAS_STATIC_ASSERT 0
#endif

void versionControl() {
printf("\n=== 版本控制和特性检测 ===\n");

printf("当前版本:%d.%d.%d (build %d)\n",
VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_BUILD);
printf("版本号:%d\n", CURRENT_VERSION);
printf("C标准:%s\n", C_STANDARD);

#if FEATURE_NEW_API
printf("新API功能可用\n");
#else
printf("新API功能不可用\n");
#endif

#if FEATURE_ADVANCED_LOGGING
printf("高级日志功能可用\n");
#else
printf("高级日志功能不可用\n");
#endif

#if HAS_STATIC_ASSERT
printf("支持静态断言\n");
#else
printf("不支持静态断言\n");
#endif
}

3. 高级宏技巧

宏递归和展开控制

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <stdio.h>

// 递归宏(需要小心使用)
#define REPEAT_1(x) x
#define REPEAT_2(x) REPEAT_1(x) REPEAT_1(x)
#define REPEAT_4(x) REPEAT_2(x) REPEAT_2(x)
#define REPEAT_8(x) REPEAT_4(x) REPEAT_4(x)

// 计数宏
#define COUNT_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N
#define COUNT_ARGS(...) COUNT_ARGS_IMPL(__VA_ARGS__,10,9,8,7,6,5,4,3,2,1,0)

// 条件宏
#define IF_ELSE(condition, true_val, false_val) \
IF_ELSE_IMPL(condition, true_val, false_val)
#define IF_ELSE_IMPL(condition, true_val, false_val) \
IF_ELSE_##condition(true_val, false_val)
#define IF_ELSE_0(true_val, false_val) false_val
#define IF_ELSE_1(true_val, false_val) true_val

// 类型安全的最大值宏
#define SAFE_MAX(a, b) ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
(_a > _b) ? _a : _b; \
})

void advancedMacroTricks() {
printf("\n=== 高级宏技巧 ===\n");

// 重复宏测试
printf("重复宏测试:");
REPEAT_4(printf("* "));
printf("\n");

// 参数计数测试
printf("参数个数测试:\n");
printf("COUNT_ARGS(a) = %d\n", COUNT_ARGS(a));
printf("COUNT_ARGS(a,b,c) = %d\n", COUNT_ARGS(a,b,c));
printf("COUNT_ARGS(1,2,3,4,5) = %d\n", COUNT_ARGS(1,2,3,4,5));

// 条件宏测试
printf("\n条件宏测试:\n");
printf("IF_ELSE(1, \"true\", \"false\") = %s\n", IF_ELSE(1, "true", "false"));
printf("IF_ELSE(0, \"true\", \"false\") = %s\n", IF_ELSE(0, "true", "false"));

// 类型安全宏测试(GCC扩展)
#ifdef __GNUC__
int x = 10, y = 20;
float a = 3.14f, b = 2.71f;
printf("\n类型安全宏测试:\n");
printf("SAFE_MAX(%d, %d) = %d\n", x, y, SAFE_MAX(x, y));
printf("SAFE_MAX(%.2f, %.2f) = %.2f\n", a, b, SAFE_MAX(a, b));
#endif
}

宏生成代码模板

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <stdio.h>
#include <stdlib.h>

// 生成getter和setter函数
#define DECLARE_PROPERTY(type, name) \
type get_##name(); \
void set_##name(type value);

#define IMPLEMENT_PROPERTY(type, name) \
static type _##name; \
type get_##name() { return _##name; } \
void set_##name(type value) { _##name = value; }

// 生成比较函数
#define DECLARE_COMPARE_FUNC(type) \
int compare_##type(const void *a, const void *b) { \
type va = *(const type*)a; \
type vb = *(const type*)b; \
return (va > vb) - (va < vb); \
}

// 生成数组操作函数
#define DECLARE_ARRAY_FUNCS(type) \
void print_##type##_array(const type *arr, int size) { \
printf(#type " array: "); \
for (int i = 0; i < size; i++) { \
printf("%d ", (int)arr[i]); \
} \
printf("\n"); \
} \
void sort_##type##_array(type *arr, int size) { \
qsort(arr, size, sizeof(type), compare_##type); \
}

// 实现属性
IMPLEMENT_PROPERTY(int, counter)
IMPLEMENT_PROPERTY(float, ratio)

// 实现比较函数
DECLARE_COMPARE_FUNC(int)
DECLARE_COMPARE_FUNC(float)

// 实现数组函数
DECLARE_ARRAY_FUNCS(int)
DECLARE_ARRAY_FUNCS(float)

void codeGeneration() {
printf("\n=== 代码生成模板 ===\n");

// 测试属性
set_counter(42);
set_ratio(3.14f);
printf("counter = %d\n", get_counter());
printf("ratio = %.2f\n", get_ratio());

// 测试数组操作
int int_arr[] = {5, 2, 8, 1, 9, 3};
int int_size = sizeof(int_arr) / sizeof(int_arr[0]);

printf("\n排序前:");
print_int_array(int_arr, int_size);

sort_int_array(int_arr, int_size);
printf("排序后:");
print_int_array(int_arr, int_size);

float float_arr[] = {3.14f, 1.41f, 2.71f, 1.73f};
int float_size = sizeof(float_arr) / sizeof(float_arr[0]);

printf("\n浮点数组排序前:");
print_float_array(float_arr, float_size);

sort_float_array(float_arr, float_size);
printf("浮点数组排序后:");
print_float_array(float_arr, float_size);
}

4. 调试和诊断宏

断言和调试宏

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <stdio.h>
#include <stdlib.h>

// 自定义断言宏
#ifdef DEBUG
#define ASSERT(condition, message) do { \
if (!(condition)) { \
fprintf(stderr, "Assertion failed: %s\n", message); \
fprintf(stderr, "File: %s, Line: %d\n", __FILE__, __LINE__); \
fprintf(stderr, "Function: %s\n", __func__); \
abort(); \
} \
} while(0)
#else
#define ASSERT(condition, message) ((void)0)
#endif

// 函数跟踪宏
#define TRACE_ENTER() printf("[TRACE] Entering %s\n", __func__)
#define TRACE_EXIT() printf("[TRACE] Exiting %s\n", __func__)
#define TRACE_POINT(msg) printf("[TRACE] %s: %s\n", __func__, msg)

// 性能测量宏
#include <time.h>
#define BENCHMARK_START() \
clock_t _start_time = clock();

#define BENCHMARK_END(operation) do { \
clock_t _end_time = clock(); \
double _elapsed = ((double)(_end_time - _start_time)) / CLOCKS_PER_SEC; \
printf("[BENCHMARK] %s took %.6f seconds\n", operation, _elapsed); \
} while(0)

// 内存检查宏
#define SAFE_FREE(ptr) do { \
if (ptr != NULL) { \
free(ptr); \
ptr = NULL; \
printf("[MEMORY] Freed pointer at %s:%d\n", __FILE__, __LINE__); \
} \
} while(0)

void debuggingMacros() {
printf("\n=== 调试和诊断宏 ===\n");

TRACE_ENTER();

// 断言测试
int value = 10;
ASSERT(value > 0, "Value must be positive");
TRACE_POINT("Assertion passed");

// 性能测试
BENCHMARK_START();

// 模拟一些工作
volatile int sum = 0;
for (int i = 0; i < 1000000; i++) {
sum += i;
}

BENCHMARK_END("Loop calculation");

// 内存管理测试
int *ptr = (int*)malloc(sizeof(int) * 10);
if (ptr != NULL) {
printf("[MEMORY] Allocated pointer\n");
SAFE_FREE(ptr);
}

TRACE_EXIT();
}

编译时信息宏

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
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>

// 编译时信息
#define COMPILE_INFO() do { \
printf("编译信息:\n"); \
printf(" 文件:%s\n", __FILE__); \
printf(" 日期:%s\n", __DATE__); \
printf(" 时间:%s\n", __TIME__); \
printf(" 行号:%d\n", __LINE__); \
printf(" 函数:%s\n", __func__); \
} while(0)

// 静态断言(C11)
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define STATIC_ASSERT(condition, message) _Static_assert(condition, message)
#else
#define STATIC_ASSERT(condition, message) \
typedef char static_assert_##__LINE__[(condition) ? 1 : -1]
#endif

// 编译时大小检查
#define CHECK_SIZE(type, expected_size) \
STATIC_ASSERT(sizeof(type) == expected_size, \
"Size of " #type " is not " #expected_size)

void compileTimeInfo() {
printf("\n=== 编译时信息 ===\n");

COMPILE_INFO();

// 静态断言测试
STATIC_ASSERT(sizeof(int) >= 4, "int must be at least 4 bytes");
STATIC_ASSERT(sizeof(char) == 1, "char must be 1 byte");

printf("\n类型大小检查:\n");
printf("sizeof(int) = %zu\n", sizeof(int));
printf("sizeof(long) = %zu\n", sizeof(long));
printf("sizeof(void*) = %zu\n", sizeof(void*));
}

5. 主函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main() {
printf("C语言预处理器高级技巧示例\n");
printf("==============================\n");

basicMacros();
stringifyAndConcat();
variableMacros();
conditionalCompilation();
versionControl();
advancedMacroTricks();
codeGeneration();
debuggingMacros();
compileTimeInfo();

return 0;
}

总结

预处理器的高级技巧包括:

  1. 宏定义技巧:函数式宏、多行宏、字符串化和连接
  2. 可变参数宏:灵活的日志系统和调试工具
  3. 条件编译:平台适配、特性控制、版本管理
  4. 高级宏技巧:递归宏、参数计数、类型安全
  5. 代码生成:自动生成重复代码模板
  6. 调试诊断:断言、跟踪、性能测量
  7. 编译时检查:静态断言、类型大小验证

合理使用预处理器能够提高代码的可维护性和可移植性,但要注意避免过度使用导致代码难以理解。

版权所有,如有侵权请联系我