首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

GNU C __attribute__ 機制全解析:函數/變量/類型屬性、兼容性宏與實戰案例

     編輯:關於C語言

__attribute__ 核心語法


__attribute__ ((attribute-list))
// 雙下劃線前後,雙括號包裹屬性列表,多屬性逗號分隔

GCC/Clang 擴展,提供編譯器優化提示、檢查增強、ABI 控制等能力。MSVC 不支持,需條件編譯隔離。

函數屬性 (Function Attributes)

1. format - 格式化字符串檢查


// 類 printf 檢查:第 1 參數為格式串,第 2 參數起檢查
extern void my_log(const char *fmt, ...) __attribute__((format(printf, 1, 2)));

// 類 scanf 檢查
extern void my_scan(const char *fmt, ...) __attribute__((format(scanf, 1, 2)));

// 成員函數:隱含 this 指針佔第 1 參數,故從 2、3 開始
struct Logger {
    void log(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
};

編譯器會對調用處參數與格式串匹配性報警 (需 -Wall),極大減少 printf("%s", 123) 類 Bug。

2. noreturn - 函數永不返回


void abort(void) __attribute__((noreturn));
void exit(int) __attribute__((noreturn));
void my_fatal(const char *msg) __attribute__((noreturn));

// 用法:避免「控制路徑到達非 void 函數末尾」警告
int foo(int x) {
    if (x < 0) my_fatal("負值");
    return x * 2;  // 編譯器知 my_fatal 不返回,無警告
}

3. const/pure - 無副作用優化

屬性語義適用場景
const純函數:無副作用,返回值僅依賴參數,不讀全局內存數學函數、哈希、校驗和
pure純函數:無副作用,返回值依賴參數和全局內存只讀全局配置的查詢函數

int square(int x) __attribute__((const));
int get_config(int key) __attribute__((pure));  // 讀只讀全局配置

// 優化效果:循環中重複調用同參數 → 單次調用 + 緩存結果
for (int i = 0; i < 100; i++) total += square(5);  // 只調用 1 次 square(5)

4. constructor/destructor - 自動初始化/清理


void my_init(void) __attribute__((constructor));
void my_fini(void) __attribute__((destructor));

// my_init 在 main 之前自動調用 (優先級可指定: constructor(101))
// my_fini 在 main 返回或 exit() 後自動調用
// 用途:庫自動註冊、環境初始化、檢測工具注入

5. 其他常用函數屬性

屬性作用
malloc返回非空、不重疊指針,優化別名分析
alloc_size(n)第 n 參數為分配大小,優化檢查
nonnull(n...)指定參數不可為 NULL,空指針檢查
returns_nonnull返回值非 NULL
warn_unused_result忽略返回值報警
deprecated調用處報警棄用
alias("name")創建別名符號
visibility("hidden")符號不導出動態庫

變量屬性 (Variable Attributes)


// 對齊:強制 32 位元組對齊 (利於 SIMD、緩存行)
int buffer[1024] __attribute__((aligned(32)));

// 緊湊:最小對齊 (結構體無填充)
struct Packed { char c; int i; } __attribute__((packed)) p;

// 未使用變量不警告
int debug_unused __attribute__((unused));

// 棄用變量
int old_api __attribute__((deprecated("用 new_api")));

// 段屬性:放入特定段
char firmware_data[] __attribute__((section(".firmware"))) = "...";

// 線程局部存儲
__thread int tls_var __attribute__((tls_model("initial-exec")));

類型屬性 (Type Attributes)


// 結構體對齊
struct Aligned8 { short a; char b; } __attribute__((aligned(8)));
// sizeof = 8 (非對齊為 4)

// 透明聯合:參數可直接傳遞聯合成員類型
typedef union { int i; float f; } __attribute__((transparent_union)) IntFloat;
void func(IntFloat u);  // 可傳 int 或 float,自動轉換

// 向量類型 (SIMD)
typedef int v4si __attribute__((vector_size(16)));  // 4 x int
v4si a = {1,2,3,4}, b = {5,6,7,8};
v4si c = a + b;  // {6,8,10,12} 向量化運算

多屬性組合與兼容性宏


// 寫法 1: 多個 __attribute__
void func(void) __attribute__((noreturn)) __attribute__((format(printf,1,2)));

// 寫法 2: 單個 __attribute__ 多屬性
void func(void) __attribute__((noreturn, format(printf,1,2)));

// 跨編譯器兼容:非 GNU 定義為空
#ifndef __GNUC__
#define __attribute__(x)  /* nothing */
#endif

// 標準庫風格使用
#if defined(__GNUC__) || defined(__clang__)
#define ATTR_NORETURN __attribute__((noreturn))
#define ATTR_FORMAT(fmt, first) __attribute__((format(printf, fmt, first)))
#else
#define ATTR_NORETURN
#define ATTR_FORMAT(fmt, first)
#endif

void die(const char *fmt, ...) ATTR_NORETURN ATTR_FORMAT(1,2);

實戰案例:安全字符串複製函數


#include <string.h>
#include <stdarg.h>

// 返回值非 NULL、參數 1/2 非 NULL、格式串檢查、棄用警告
char *safe_strcpy(char *dest, const char *src) 
    __attribute__((returns_nonnull, nonnull(1,2), warn_unused_result));

char *safe_strcpy(char *dest, const char *src) {
    return strcpy(dest, src);  // 實際應用用 strlcpy/strncpy_s
}

// 格式化輸出封裝
void log_info(const char *fmt, ...) 
    __attribute__((format(printf, 1, 2)));

void log_info(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    va_end(ap);
}

// 測試
int main() {
    char buf[100];
    safe_strcpy(buf, "hello");  // 正常
    // safe_strcpy(NULL, "x");  // 編譯警告: null argument
    log_info("數值: %d", 42);   // 正常
    // log_info("數值: %s", 42); // 編譯警告: format '%s' expects 'char*'
    return 0;
}

查看支持屬性列表


# GCC
gcc --target-help | grep attribute

# Clang
clang -cc1 -fsyntax-only --help | grep attribute

# 官方文檔
# https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
# https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
# https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved