C 参考手册
- C 语言
- C 的历史
- 基本概念
- 表达式
- 声明
- 初始化
- 函数
- 语句
- 静态断言
- 字符常量
- 函数声明
- 函数定义
- 转义序列
- 翻译阶段
- 标识符
- 作用域
- 生存期
- 查找与命名空间
- ASCII 码表
- 类型
- 遵从性
- 算术类型
- restrict 类型限定符
- 类型
- 对象与对齐
- 主函数
- 未定义行为
- 内存模型
- if 语句
- switch 语句
- for 循环
- while 循环
- do-while 循环
- continue语句
- break 语句
- goto语句
- return 语句
- 值类别
- 求值顺序
- 整数常量
- 浮点常量
- 字符串字面量
- 复合字面量
- 常量表达式
- 隐式转换
- 成员访问运算符
- 逻辑运算符
- 比较运算符
- 算术运算符
- 赋值运算符
- 自增/自减运算符
- 其他运算符
- sizeof 运算符
- _Alignof 运算符
- 转型运算符
- C 运算符优先级
- 泛型选择
- 标量初始化
- 数组初始化
- 结构体与联合体初始化
- 指针声明
- 数组声明
- 枚举
- 存储类指定符
- const 类型限定符
- volatile 类型限定符
- 结构体声明
- 联合体声明
- 位域
- _Alignas
- typedef 声明
- 原子类型
- 外部及试探性定义
- inline 函数指定符
- _Noreturn 函数指定符
- 变长参数
- 内联汇编
- 可分析性
- 替用运算符及记号
- C 关键词
- 预处理器
- C 标准库头文件
- 类型支持
- 程序支持工具
- 变参数函数
- 错误处理
- 动态内存管理
- 日期和时间工具
- 字符串库
- 算法
- 数值
- 文件输入/输出
- 本地化支持
- 原子操作库
- 线程支持库
- 实验性 C 标准库
- 有用的资源
- 符号索引
- 注释
复合字面量
就地构造一个指定类型的无名对象,在只需要一次数组、结构体或联合体变量时使用。
语法
( type ) { initializer-list }
|
(C99 起) | ||||||||
其中
type | - | 指定任何完整对象类型或未知大小的数组的类型名,但不能是 VLA |
initializer-list | - | 适合 type 类型变量初始化的初始化器列表 |
解释
复合字面量构造一个 type 所指定类型的无名对象,并以 initializer-list 的指定初始化之。
复合字面量的类型是 type (除非 type 是未知大小的数组;如在数组初始化中一般从 initializer-list 推导出其大小)。
复合字面量的值类别是左值(能取其地址)。
若复合字面量出现于文件作用域,则其求值所得的无名对象拥有静态存储期,若复合字面量出现于块作用域,则该对象拥有自动存储期(此情况下对象的生存期结束于外围块的结尾)。
注意
字符或宽字符数组类型的 const 限定复合字面量,可能会与字符串字面量共享存储。
(const char []){"abc"} == "abc" // 可以为 1 或 0 ,实现定义
每个复合字面量仅在其作用域内创建一个对象:
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; // 注意:若使用循环,则其作用域会结束于此, // 这会终止复合字面量的生存期, // 令 p 为悬垂指针 return p == q && q->i == 1; // 始终返回 1 }
因为复合字面量是无名的,一个复合字面量不能引用自身(一个具名结构体可以包含指向其自身的指针)。
虽然复合字面量的语法和转型相似,重要的区别是转型是非左值表达式,而复合字面量是左值。
示例
运行此代码
int *p = (int[]){2, 4}; // 创建一个无名的 int[2] 类型静态存储数组 // 初始数组为值 {2, 4} // 创建指向数组首元素的指针 p const float *pc = (const float []){1e0, 1e1, 1e2}; // 只读复合字面量 int main(void) { int n = 2, *p = &n; p = (int [2]){*p}; // 创建一个无名的 int[2] 类型自动存储数组 // 初始化首个元素为之前 *p 所持有的值 // 初始化第二个元素为零 // 将首元素的地址存储到 p struct point {double x,y;}; void drawline1(struct point from, struct point to); void drawline2(struct point *from, struct point *to); drawline1((struct point){.x=1, .y=1}, // 创建二个块作用域的结构体 (struct point){.x=3, .y=4}); // 然后调用 drawline1 ,以值传递 drawline2(&(struct point){.x=1, .y=1}, // 创建二个块作用域的结构体 &(struct point){.x=3, .y=4}); // 然后调用 drawline2 ,传递其地址 }
引用
- C11 standard (ISO/IEC 9899:2011):
- 6.5.2.5 Compound literals (p: 85-87)
- C99 standard (ISO/IEC 9899:1999):
- 6.5.2.5 Compound literals (p: 75-77)