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

C99 新特性:複合字面量完整指南

     編輯:關於C

Compound Literals:C 語言的「即時建構」超能力

C99 引入的複合字面量,讓陣列、結構體能像純量常值一樣「即時建立、即時使用」,極大提升程式碼表達力與簡潔度。

基本語法

(型別) { 初始化列表 }
// 回傳:指向匿名物件的指標(左值)

陣列複合字面量

// 即時建立 int 陣列指標
int *arr1 = (int[]) {1, 2, 3};
int *arr2 = (int[10]) {0}; // 指定大小,其餘補 0

// 重新指派(舊陣列若無其他引用將洩漏,除非靜態儲存期)
arr1 = (int[]) {4, 5, 6};

// 傳遞給函數(最常見用法)
void process(int *data, int len);
process((int[]) {10, 20, 30}, 3); // 無需命名變數

結構體複合字面量

typedef struct {
    void *data;
    int len;
} Array;

Array *a1 = (Array[]) {{NULL, 0}};           // 陣列包含 1 個結構體
Array *a2 = (Array[1]) {{(int[]){42}, 1}};   // 巢狀:結構體含陣列指標

// 函數呼叫時即時建構
void foo(Array *arr);
foo((Array[]) {{(int[]){1,2,3}, 3}});

靜態儲存期:模組級常數資料

// 檔案作用域:靜態儲存期,程式啟動時建立,結束時銷毀
static const Array *CONFIG = (Array[]) {
    {(int[10]){0}, 10},  // 預設緩衝區
    {(int[]){1,2,3}, 3}  // 預設參數
};

左值特性:可修改、可取址

int *p = (int[]){1,2,3};
p[0] = 99;              // 合法!複合字面量是左值
int *q = &p[1];         // 可取元素址

// 甚至可對整個字面量取址(指向陣列的指標)
int (*arrPtr)[3] = &(int[3]){1,2,3};

儲存期規則

實戰範例:簡化結構體初始化

// 傳統寫法:需命名中間變數
int data[] = {1, 2, 3};
Array arr = {data, 3};
foo(&arr);

// 複合字面量:一行完成
foo(&(Array){(int[]){1,2,3}, 3});

// 更複雜的巢狀結構
typedef struct { int x, y; } Point;
typedef struct { Point pts[3]; int n; } Polygon;

void draw(Polygon *p);
draw(&(Polygon){{{0,0}, {10,0}, {5,10}}, 3});

進階黑魔法

  • 可變長度陣列 (VLA) 複合字面量:(int[n]){0} 動態大小
  • 指定初始化器結合:(struct){.x=1, .y=2} (C99)
  • 泛型選擇配合:_Generic 做型別多態 (C11)

注意事項與陷阱

  1. 儲存期陷阱:函數內複合字面量在區塊結束時失效,不可回傳其指標
  2. 記憶體洩漏:重複指派給同一指標變數,舊字面量無法釋放(自動儲存期除非手動管理)
  3. 不可用於常數運算式:enum { N = (int[]){1}[0] } 非法
  4. C++ 不支援:C++ 採用建構函數/初始化列表,{} 語法語意不同

總結

複合字面量是 C99 最實用的特性之一,將「建構資料」與「使用資料」合二為一,配合指定初始化器、VLA、靜態儲存期,能寫出極具表達力的程式碼。掌握其儲存期規則,避免懸空指標,即可安心使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
位置儲存期生命週期
區塊作用域 (函數內)自動進入區塊建立,離開區塊銷毀
檔案作用域 (全域)靜態程式啟動建立,結束銷毀