GCC 擴展屬性 `__attribute__` 是 C/C++ 進階開發利器,用於編譯器優化提示、代碼檢查、符號控制、ABI 兼容等。本文梳理官方文檔語法規則,並通過四個高頻屬性(`alias`、`deprecated`、`format`、`weak`)實戰演示。
__attribute__ (( attribute-list ))
// attribute-list: 逗號分隔的屬性序列
// 屬性形式:
// 1. 空(忽略)
// 2. 單詞:unused, noreturn, const 等
// 3. 單詞 + 參數:format(printf, 1, 2), alias("oldname")
屬性可出現於:標籤後、struct/union/enum 定義、聲明符前、參數聲明、類型限定符中等位置,作用於實體(函數/變量/類型/參數)。
void foo() { printf("In %s\n", __func__); }
void _foo() __attribute__((alias("foo"))); // 聲明別名
int main() { _foo(); } // 輸出 "In foo"
場景: 庫版本兼容、內部實現與公開 API 解耦、glibc 大量使用(如 `_strong_alias` 宏)。
__attribute__((deprecated("foo() 已棄用,請用 bar()")))
void foo() { ... }
int main() { foo(); } // 編譯警告:warning: 'foo' is deprecated: foo() 已棄用...
作用: 編譯期發現舊接口調用,平滑遷移 API。
void my_log(const char *fmt, ...)
__attribute__((format(printf, 1, 2))); // 第1參數fmt, 第2參數起檢查
void test() {
my_log("%d %s", 123); // 警告:格式要求 2 參數,僅給 1
my_log("%s", 123); // 警告:%s 需 char*,傳 int
}
原型參數: `format(archetype, string-index, first-to-check)`
`archetype`:`printf`/`scanf`/`strftime`/`strfmon` 等;
`string-index`:格式字符串參數位置(從 1 計);
`first-to-check`:首個被檢查參數位置。
// lib.c
void __attribute__((weak)) default_handler() { puts("default"); }
// app.c
void default_handler() { puts("custom"); } // 強定義覆蓋弱定義
// 鏈接時:若 app.c 定義,用 custom;否則用 default,不報重定義錯誤
場景: 庫提供默認實現,應用可選覆蓋;中斷向量表、鉤子函數預留。
| 屬性 | 作用對象 | 用途 |
|---|---|---|
| noreturn | 函數 | 函數永不返回(exit/abort/長跳轉),優化調用點 |
| unused | 變量/參數/函數 | 抑制「未使用」警告 |
| packed | struct/union | 取消對齊填充,節省空間/匹配硬件佈局 |
| aligned(n) | 變量/類型/字段 | 指定 n 字節對齊(SIMD、DMA、緩存行) |
| cleanup(func) | 自動變量 | 作用域結束自動調用 func(RAII 模擬) |
| constructor/destructor | 函數 | main 前/後自動執行(模塊初始化/清理) |