C/C++ 編譯前會先經過預處理器處理。預處理器讀取原始碼,處理以 # 開頭的指令(如 #include、#define、#if 等),進行宏展開、檔案包含、條件編譯等轉換,並移除註解與多餘空白字元。預處理指令不屬於 C++ 語法,而是指導編譯器對原始碼進行文字級別的替換與調整。
#include#include 會在指令處展開被包含檔案的內容,支援多重嵌套(標準 C 至少支援 8 層)。預處理器不會自動防止重複包含,開發者需自行在頭檔中使用條件編譯防護:
#ifndef MY_H
#define MY_H
// 頭檔內容
#endif
兩種包含格式:
#include <header.h>:搜尋編譯器內建/外部庫目錄。#include "header.h":先搜尋當前專案目錄,找不到再搜尋編譯器目錄。這區分了公共庫頭檔與專案私有頭檔。
#define定義符號代表特定值或字串,慣用全大寫命名:
#define MAX_NUM 10
#define VERSION "Version 1.0"
宏值可以是常量表達式,可引用先前定義的宏。建議加括號避免運算優先級問題:
#define ONE 1
#define TWO 2
#define THREE (ONE + TWO) // 正確
// #define THREE ONE + TWO // 危險:six = THREE * TWO 會展開為 1 + 2 * 2 = 5
類似函數調用,但在調用處直接展開:
#define CUBE(x) ((x) * (x) * (x))
參數與整體表達式都要加括號。避免傳入有副作用的表達式(如 CUBE(num++) 會導致 num 遞增三次)。
# 與連接運算符 ### 將參數轉為字串常值:#define STR(x) "Value: " #x → STR(42) 展開為 "Value: 42"。## 將參數連接成單一符號:#define CONCAT(a,b) a##b → CONCAT(var, 1) 變為 var1。根據常量表達式或宏定義決定是否編譯程式碼區塊:
#if / #elif / #else / #endif:判斷常量表達式真假。#ifdef / #ifndef:判斷宏是否已定義。等價於 #if defined(MACRO) / #if !defined(MACRO)。常見用法:除錯開關、平台差異處理、防止重複包含。
#error:停止編譯並顯示錯誤訊息。#line:修改編譯器報告的行號/檔案名。#pragma:編譯器特定擴展(如抑制警告)。#pragma once 或 #ifndef)。const、constexpr、inline 函數替代宏,提高型別安全與除錯體驗。