| 指令 | 用途 | 典型場景 |
|---|---|---|
| `#ifdef` / `#ifndef` | 檢查宏**是否定義** | 防重複包含、平台專用代碼、功能開關 |
| `#if` / `#elif` / `#else` | 檢查**常數表達式真假** | 版本比較、數值範圍、複雜邏輯組合 |
| `#endif` | 結束條件區塊 | 配對使用,不可省略 |
/* mylib.h */
#ifndef MYLIB_H
#define MYLIB_H
/* 介面宣告 */
void mylib_init(void);
#endif /* MYLIB_H */
現代替代:`#pragma once` (GCC/Clang/MSVC 全支援),更簡潔無命名衝突風險。
/* platform.h */
#if defined(_WIN32) || defined(_WIN64)
#define PLATFORM_WINDOWS 1
#define DLLEXPORT __declspec(dllexport)
#include
#elif defined(__linux__)
#define PLATFORM_LINUX 1
#define DLLEXPORT __attribute__((visibility("default")))
#include
#elif defined(__APPLE__)
#define PLATFORM_MACOS 1
#define DLLEXPORT __attribute__((visibility("default")))
#else
#error "Unsupported platform"
#endif
/* config.h - 專案統一配置 */
#define ENABLE_LOGGING 1
#define ENABLE_STATS 0
#define MAX_CONNECTIONS 1024
#define PROTOCOL_VERSION 2
/* 業務代碼 */
#if ENABLE_LOGGING
#define LOG(fmt, ...) fprintf(stderr, "[LOG] " fmt "\n", ##__VA_ARGS__)
#else
#define LOG(fmt, ...) ((void)0)
#endif
#if PROTOCOL_VERSION >= 2
#define HEADER_SIZE 16
#else
#define HEADER_SIZE 8
#endif
編譯時可覆蓋:`gcc -DENABLE_STATS=1 -DPROTOCOL_VERSION=3 ...`
#if VERSION_MAJOR > 2 || (VERSION_MAJOR == 2 && VERSION_MINOR >= 5)
#define FEATURE_NEW_API 1
#else
#define FEATURE_NEW_API 0
#endif
#if defined(FEATURE_A) && defined(FEATURE_B) && !defined(FEATURE_C)
#define COMBO_AB_ONLY 1
#endif
/* C11 標準靜態斷言 */
_Static_assert(sizeof(int) == 4, "int_must_be_32bit");
_Static_assert(MAX_CONNECTIONS > 0, "max_conn_positive");
/* 舊標準相容技巧 */
#define COMPILE_TIME_ASSERT(cond, msg) \
typedef char assert_##msg[(cond) ? 1 : -1]
COMPILE_TIME_ASSERT(CHAR_BIT == 8, char_is_8bit);
#ifdef NDEBUG
#define ASSERT(cond) ((void)0)
#define TRACE(fmt, ...) ((void)0)
#else
#define ASSERT(cond) \
do { if (!(cond)) { fprintf(stderr, "ASSERT: %s:%d: %s\n", __FILE__, __LINE__, #cond); abort(); } } while(0)
#define TRACE(fmt, ...) fprintf(stderr, "[TRACE] " fmt "\n", ##__VA_ARGS__)
#endif
發布編譯:`gcc -DNDEBUG -O2 ...` 自動移除斷言與追蹤代碼。
#define STR(x) #x
#define CAT(a,b) a##b
STR(hello) // "hello"
CAT(var, 1) // var1
#define SAFE_FREE(p) \
do { free(p); (p) = NULL; } while(0)
#if DEBUG_LEVEL >= 2
#define VERBOSE_LOG 1
#endif
#if defined(UNKNOWN_MACRO) && UNKNOWN_MACRO > 0 /* 安全寫法 */
#if UNKNOWN_MACRO > 0 /* 危險:未定義視為 0,GCC -Wundef 會警告 */
| 錯誤 | 修正 |
|---|---|
| `#ifdef MACRO` 後無 `#endif` | 每個條件區塊必須配對 `#endif` |
| 宏定義含分號 `#define N 10;` | 宏定義**不加分號**,使用處自動補上 |
| `#if` 表達式含變數/函數呼叫 | 條件編譯**僅支援編譯期常數表達式** |
| 巢狀條件編譯縮進混亂 | 保持一致縮進,IDE 可自動摺疊 |
條件編譯是 C 語言**編譯期多態**的核心工具。善用衛兵、平台抽象、配置開關、版本矩陣、靜態斷言、除錯切換,能構建高度可配置、跨平台、零開銷抽象的代碼庫。原則:**業務邏輯用 `if`,編譯期配置用 `#if`,嚴禁混淆。**