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

C語言進階技巧:extern、static、柔性數組、結構體對齊與複合字面量

     編輯:關於C語言

關鍵字細節:extern 與 static

  • extern:用於**變數**宣告外部連結;用於**函式**時無意義(函式預設即為外部連結)。
  • static:
    • 修飾**函式** → 僅在本編譯單元可見(內部連結)。
    • 修飾**全域變數** → 內部連結,不汙染全域命名空間。
    • 修飾**區域變數** → 延長生命週期至程式結束,儲存於 .bss/.data 段。

呼叫慣例(__cdecl/__stdcall/__fastcall)、DLL 匯出入(__declspec(dllexport/import))、語言連結(extern "C")**僅需在標頭檔宣告**,實作檔不必重複。

非標準記憶體分配技巧:柔性數組成員

C99 前常見寫法(結構體尾端宣告長度為 1 的陣列),配合 malloc(sizeof(Struct)-1 + len) 實現變長結構體:

struct Name {
    int  len;
    char str[1];  // 柔性數組成員 (C99 標準寫法為 char str[])
};

struct Name* make_name(const char* s) {
    struct Name* p = malloc(sizeof(struct Name) - 1 + strlen(s) + 1);
    if (p) {
        p->len = (int)strlen(s);
        strcpy(p->str, s);
    }
    return p;
}

優點:單次分配、記憶體連續、快取友好。缺點:依賴編譯器不對結構體尾端填充、非標準 C89 行為(C99 已標準化為 char str[])。

C99 新特性速覽

  • 複合字面量:(int[]){5} 產生臨時陣列並取得指標,可直接傳遞給 void f(int*),類似 Java 匿名陣列。
  • 指定初始化器:struct S s = {.a=1, .b=2};、int a[10] = {[5]=99};。
  • 內聯函式:inline 關鍵字正式進入標準(C99),但編譯器可選擇忽略。
  • 可變長度陣列 (VLA):void f(int n) { int a[n]; }(C11 改為選擇性支援)。

結構體記憶體佈局與對齊

struct Demo {
    char c;   // offset 0
    int  i;   // offset 4 (假設 4 位元組對齊)
    short s;  // offset 8
};            // sizeof = 12 (尾端填充至 4 的倍數)
  • sizeof 包含填充位元組,「空洞」計算在內。
  • 欄位偏移量:標準宏 offsetof(T, m) (需 <stddef.h>);非標準手寫版:#define OFFSET(T,m) ((size_t)&(((T*)0)->m))。
  • 勿用 == 比較結構體:填充位元組內容不定,導致誤判。需逐欄位比較或 memcmp(後者同樣受填充干擾)。

指標與常數的微妙關係

  • void f(int*) 傳入常數:C99 使用複合字面量 f((int[]){42});C89 需建立暫存變數。
  • 函式名 = 代碼區位址,函式指標 = 可賦值/運算的變數,兩者皆為「可呼叫位址」,但**不可與資料指標互轉**(void(*)() vs void*)。
  • () 是函式指標唯一的後綴運算子。

NULL 與 0 的哲學

  • C 標準允許 NULL 定義為 0、0L 或 (void*)0;某些架構(如段式記憶體)以特殊位模式實現 NULL 以觸發硬體陷阱捕捉空指標解參考。
  • 規則:
    1. 需要空指標常數處 → 0 或 NULL 等價。
    2. 無原型函式/可變參數傳 0 → **必須強制轉型**:f((int*)0) 或 f((void*)NULL)。
  • 非指標場合(如 '\0'、整數 0)請勿使用 NULL。

陣列本質:指標運算的語法糖

a[i] ≡ *(a + i) ≡ i[a]。陣列非一級物件,下標運算子建立在指標運算之上。透過不同型別指標(int (*)[N] vs int*)可實現不同粒度的 ++/-- 重載。

推薦參考書

《C Programming FAQs》 (Steve Summit, 人民郵電出版社 2008) — 習題式涵蓋上述所有細節與更多陷阱,案頭必備。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved