# 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)。