名稱空間
變體
操作

複合字面量 (C99 起)

來自 cppreference.com
< c‎ | 語言

就地構造指定型別(可以是結構體、聯合體,甚至是陣列型別)的匿名物件。

目錄

[編輯] 語法

( 儲存類說明符 (可選)(C23 起) 型別 ) { 初始化列表 } (C99 起)
( 儲存類說明符 (可選)(C23 起) 型別 ) { 初始化列表 , } (C99 起)
( 儲存類說明符 (可選) 型別 ) { } (自 C23 起)

其中

儲存類說明符 - (C23 起) 只能包含 constexprstaticregisterthread_local儲存類說明符列表
型別 - 一個型別名,指定任何完整的物件型別或未知大小的陣列,但不能是 VLA
初始化器-列表 - 適合初始化 型別 物件的初始化列表

[編輯] 解釋

複合字面量表達式構造一個由 型別 指定的匿名物件,並按照 初始化列表 的指定進行初始化。指定初始化器被接受。

複合字面量的型別是 型別(除非 型別 是未知大小的陣列;其大小從 初始化列表 中推導,如同在陣列初始化中一樣)。

複合字面量的值類別是左值(可以獲取其地址)。

複合字面量所求值的匿名物件在檔案作用域時具有靜態儲存期,在塊作用域時具有自動儲存期(在這種情況下,物件的生命週期在封閉塊結束時結束)。 (直至 C23)
如果複合字面量在函式體外部且在任何引數列表外部進行求值,則它與檔案作用域相關聯;否則,它與封閉塊相關聯。根據這種關聯,儲存類說明符(可能為空)、型別名和初始化列表(如果有的話)應當適用於檔案作用域或塊作用域中的物件定義,分別如下所示:
   storage-class-specifiers typeof(type) ID = { initializer-list };
其中 ID 是在整個程式中唯一的識別符號。複合字面量提供一個匿名物件,其值、型別、儲存期和其他屬性如同由上述定義語法給出;如果儲存期是自動的,則匿名物件的例項的生命週期是封閉塊的當前執行。如果儲存類說明符包含除 constexprstaticregisterthread_local 之外的其他說明符,則行為未定義。
(自 C23 起)

[編輯] 注意

const-qualified 字元或寬字元陣列型別的複合字面量可能與字串字面量共享儲存。

(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
}

因為複合字面量是匿名的,所以複合字面量不能引用自身(一個具名結構體可以包含指向自身的指標)

雖然複合字面量的語法類似於型別轉換,但重要的區別在於型別轉換是非左值表示式,而複合字面量是左值。

[編輯] 示例

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