---
# System prepended metadata

title: Compound Literals 複合字面值
tags: [C]

---

# Compound Literals 複合字面值

## 原理

C99 標準引入 **Compound Literals**：

- **語法**: `(type_name){initializer_list}` 或 `(type_name[]){initializer_list}`
- **功能**: 在程式碼中直接建立一個未命名(unnamed)的物件 (結構、陣列等)，並回傳該物件的位址 (對於陣列，是首元素的位址)。
- **生命週期**: 若在函式內部使用，其生命週期通常與所在的區塊 (block scope) 相同。

## 使用 Compound Literals 快速建立 Linked List 節點
```c=
struct llist {
    int val;
    struct llist *next;
};
```
1.  **預定義巨集**
    ```c=5
    #define cons(x, y) (struct llist[]){x, y}
    ```
    *   建立一個匿名的 `struct llist` **陣列**，該陣列只有一個元素。
    *   C 語言會使用 `x` 來初始化這個陣列首元素 (即第一個 `struct llist`) 的第一個成員 (`val`)，並使用 `y` 來初始化第二個成員 (`next`)。
    *   整個 Compound Literal 運算式的值是這個匿名陣列**首元素**的記憶體位址 (也就是一個 `struct llist *` 指標)。
    *   **效果**: `cons(x, y)` 建立了一個新的 `struct llist` 節點，其 `val` 為 `x`，`next` 為 `y`，並回傳指向這個新節點的指標。

4.  **`main` 函式**
    ```c=6
    int main() {
        // 使用 cons 巨集建立串列 (語法簡潔)
        struct llist *list = cons(9, cons(5, cons(4, cons(7, NULL))));

        // 展開上面的巨集會得到
        struct llist *list = (struct llist[]){9, (struct llist[]){5, (struct llist[]){4, (struct llist[]){7, ((void *)0)}}}};

        struct llist *p = list;
        for (; p; p = p->next)
            printf("%d -> ", p->val);
        printf("\n");
        return 0;
    }
    ```
    *   **串列建立**:
        *   建立串列 (9 -> 5 -> 4 -> 7 -> NULL)。
        *   使用 `cons` 巨集，程式碼更易讀。

## 重點總結

*   **Compound Literals** 提供了一種在 C 程式碼中直接建立匿名物件 (尤其是結構或陣列) 的簡潔語法，並回傳其指標。
*   透過 `#define` 巨集可以將 Compound Literal 的使用包裝起來，提高程式碼可讀性 (如 `cons` 巨集)。
*   此範例展示了如何利用 Compound Literals 模擬函數式程式設計風格來建立連結串列。

## 注意事項

*   Compound Literals 是 C99 標準的一部分，需使用支援 C99 或更新標準的編譯器 (如 GCC, Clang)。