複合字面量 (自 C99 起)
出自 cppreference.com
在原地建構一個指定類型(可以是結構體、聯合體,甚至是陣列類型)的未命名物件。
目錄 |
[編輯] 語法
( 儲存類別說明符 (選用)(自 C23 起) 類型 ) { 初始化列表 } |
(自 C99 起) | ||||||||
( 儲存類別說明符 (選用)(自 C23 起) 類型 ) { 初始化列表 , } |
(自 C99 起) | ||||||||
( 儲存類別說明符 (選用) 類型 ) { } |
(C23 起) | ||||||||
其中
| 儲存類別說明符 | - | (自 C23 起) 一系列儲存類別說明符,其中只能包含 constexpr、static、register 或 thread_local |
| type (型別) | - | 一個類型名稱,指定任何完整物件類型或大小未知的陣列(但不包含 VLA) |
| 初始化器列表 | - | 適合用於初始化類型物件的初始化列表 |
[編輯] 解釋
複合字面量表達式會建構一個由 類型 指定類型的未命名物件,並依照 初始化列表 對其進行初始化。支援指定初始化器 (Designated initializers)。
複合字面量的類型即為 類型(除非 類型 為大小未知的陣列;此時其大小會如同陣列初始化一般,從 初始化列表 推導而得)。
複合字面量的數值類別為左值 (lvalue)(可以取其位址)。
| 若複合字面量出現於檔案作用域,則該複合字面量所求值的未命名物件具有靜態儲存期;若出現在區塊作用域,則具有自動儲存期(在此情況下,該物件的生命週期於包含它的區塊結束時結束)。 | (C23 之前) |
若複合字面量是在函數體外及任何參數列表外進行求值,則其與檔案作用域關聯;否則,它與包含它的區塊關聯。依據此關聯,儲存類別說明符(可能為空)、類型名稱及初始化列表(若有)必須滿足該形式下,分別於檔案作用域或區塊作用域定義物件的有效說明符要求,如下所示: storage-class-specifiers typeof(type) ID = { initializer-list };
其中 ID 是整個程式中唯一的識別碼。複合字面量提供了一個未命名物件,其數值、類型、儲存期及其他屬性就如同上述定義語法所給定者;若儲存期為自動,則該未命名物件實例的生命週期為包含它的區塊之當前執行期間。若儲存類別說明符包含了 constexpr、static、register 或 thread_local 以外的說明符,則行為未定義。 |
(C23 起) |
[編輯] 附註
被 const 限定的字元或寬字元陣列類型的複合字面量,可能會與字串字面量共享儲存空間。
(const char []){"abc"} == "abc" // might be 1 or 0, unspecified
每個複合字面量在其作用域內僅建立單一物件。
int f (void) { struct s {int i;} *p = 0, *q; int j = 0; again: q = p, p = &((struct s){ j++ }); if (j < 2) goto again; // note; if a loop were used, it would end scope here, // which would terminate the lifetime of the compound literal // leaving p as a dangling pointer return p == q && q->i == 1; // always returns 1 }
由於複合字面量是未命名的,因此複合字面量無法參照自身(而具名結構體可以包含指向自身的指標)。
雖然複合字面量的語法與轉型 (cast) 相似,但重要的區別在於:轉型是一個非左值表達式,而複合字面量是一個左值。
[編輯] 範例
執行此程式碼
#include <stdio.h> int *p = (int[]){2, 4}; // creates an unnamed static array of type int[2] // initializes the array to the values {2, 4} // creates pointer p to point at the first element of // the array const float *pc = (const float []){1e0, 1e1, 1e2}; // read-only compound literal struct point {double x,y;}; int main(void) { int n = 2, *p = &n; p = (int [2]){*p}; // creates an unnamed automatic array of type int[2] // initializes the first element to the value formerly // held in *p // initializes the second element to zero // stores the address of the first element in p void drawline1(struct point from, struct point to); void drawline2(struct point *from, struct point *to); drawline1( (struct point){.x=1, .y=1}, // creates two structs with block scope and (struct point){.x=3, .y=4}); // calls drawline1, passing them by value drawline2( &(struct point){.x=1, .y=1}, // creates two structs with block scope and &(struct point){.x=3, .y=4}); // calls drawline2, passing their addresses } void drawline1(struct point from, struct point to) { printf("drawline1: `from` @ %p {%.2f, %.2f}, `to` @ %p {%.2f, %.2f}\n", (void*)&from, from.x, from.y, (void*)&to, to.x, to.y); } void drawline2(struct point *from, struct point *to) { printf("drawline2: `from` @ %p {%.2f, %.2f}, `to` @ %p {%.2f, %.2f}\n", (void*)from, from->x, from->y, (void*)to, to->x, to->y); }
可能輸出
drawline1: `from` @ 0x7ffd24facea0 {1.00, 1.00}, `to` @ 0x7ffd24face90 {3.00, 4.00}
drawline2: `from` @ 0x7ffd24facec0 {1.00, 1.00}, `to` @ 0x7ffd24faced0 {3.00, 4.00}[編輯] 參考資料
- C23 標準 (ISO/IEC 9899:2024)
- 6.5.2.5 複合字面量 (p: 待定)
- C17 標準 (ISO/IEC 9899:2018)
- 6.5.2.5 複合字面量 (p: 61-63)
- C11 標準 (ISO/IEC 9899:2011)
- 6.5.2.5 複合字面量 (p: 85-87)
- C99 標準 (ISO/IEC 9899:1999)
- 6.5.2.5 複合字面量 (p: 75-77)