字面量是除了符号常量之外的常量。如,1是int型字面量,3.14是float型字面量,'C’是char型字面量,'Yudao’是字符串字面量。那么,数组和结构体是否也能有字面量来表示呢?如定义了这种"字面量",能带来什么好处呢(后文中逐一介绍)? 因此,C99标准委员会就新增了复合字面量(compound literals)

文章目录

  • 定义
    • 语法
    • 约束
    • 语义
  • 用法
    • 文件作用域的匿名数组
    • 函数作用域的匿名数组
    • 同一函数作用域的单例复合字面量"对象"

定义

语法

( type-name ) { initializer-list }

( type-name ) { initializer-list , }

约束

  1. The type name shall specify an object type or an array of unknown size, but not a variable length array type.

type name指定了数组类型或结构体类型,数组长度不能是可变的。

  1. No initializer shall attempt to provide a value for an object not contained within the entire unnamed object specified by the compound literal.

匿名"对象"的初始化必须在在复合字面量的大括号中。

  1. If the compound literal occurs outside the body of a function, the initializer list shall consist of constant expressions.

如果复合字面量是文件作用域,initializer list的表达式必须是常量表达式。

语义

  1. A postfix expression that consists of a parenthesized type name followed by a brace enclosed list of initializers is a compound literal. It provides an unnamed object whose value is given by the initializer list.

    一个由( type-name ) { initializer-list }构成的后缀表达式就是复合字面量,它定义了一个匿名"对象",该"对象"的值由initializer list指定。

  2. If the type name specifies an array of unknown size, the size is determined by the initializer list as specified in 6.7.8, and the type of the compound literal is that of the completed array type. Otherwise (when the type name specifies an object type), the type of the compound literal is that specified by the type name. In either case, the result is an lvalue.

    如果type name是一个匿名数组,那么该数组的长度由initializer list的元素个数决定。复合字面量可以作为左值。

  3. The value of the compound literal is that of an unnamed object initialized by the initializer list. If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.

    复合字面量的值是由initializer list指定。如果复合字面量是文件作用域,该"对象"是static storage duration;如果复合字面量是函数作用域或块作用域,该"对象"是automatic storage duration。

  4. All the semantic rules and constraints for initializer lists in 6.7.8 are applicable to
    compound literals.

用法

文件作用域的匿名数组

#include <stdio.h>
#include <stdlib.h>int *p = (int[]){1, 2, 3};
int *p2 = (int[]){1, 2, 3};int main(int argc, char** argv)
{printf("p=%p\n", p);printf("p2=%p\n", p2); return 0;
}// 运行结果为
// p=0x55764bdc4010
// p2=0x55764bdc4020

文件作用域(file scope)定义复合字面量,initializer-list中的表达式必须为常量。文件作用域的复合字面量,具有static storage duration,存储在.data section

函数作用域的匿名数组

#include <stdio.h>
#include <stdlib.h>int main(int argc, char** argv)
{int a[32] = {4,5,6};int *p = (int[]){1, 2, 3};printf("&a[0]=%p\n", &a[0]);printf("p=%p\n", p);return 0;
}// 运行结果
// &a[0]=0x7ffff11d2fb0
// p=0x7ffff11d2fa4

函数作用域的复合字面量,具有automatic storage duration,从打印的地址可以知道,匿名数组存储在栈上。(栈特点:向低地址方向增长)


"/tmp/fileXXXXXX" // static storage duration;数组类型为char;数组内容不能修改
(char []){"/tmp/fileXXXXXX"} // 在函数作用域内时,automatic storage duration,该匿名数组的内容可以修改
(const char []){"/tmp/fileXXXXXX"} // 在函数作用域内时,automatic storage duration,因为有const修饰,该匿名数组的内容不可以修改
// 与字符串字面量(如,"abc")类似,const修饰的复合字面量也可是read-only memory和can even be shared
(const char []){"abc"} == "abc"
// 如果字面量的storage是shared,该表达式为真。
// storage is shared该怎么理解?

同一函数作用域的单例复合字面量"对象"

为了讲清楚什么是 单例 复合字面量"对象",先看如下代码

#include <stdio.h>
#include <stdlib.h>struct s { int i; };// 函数f的返回值总是为1
int f (void)
{struct s *p = 0, *q;int j = 0;again:q = p, p = &((struct s){ j++ });printf("p=%p\n", p);if (j < 2) goto again;return p == q && q->i == 1;
}// 函数f2的返回值也总是为1
int f2 (void)
{struct s *p = 0, *q;int j = 0;while(j < 2){q = p, p = &((struct s){ j++ });printf("p=%p\n", p);}return p == q && q->i == 1;
}int main(int argc, char** argv)
{printf("f() return:%d\n", f());printf("f() return:%d\n", f());printf("f() return:%d\n", f());printf("f2() return:%d\n", f2());printf("f2() return:%d\n", f2());printf("f2() return:%d\n", f2());return 0;
}

看一下,运行结果:

p=0x7fff543fa7f0
p=0x7fff543fa7f0
f() return:1
p=0x7fff543fa7f0
p=0x7fff543fa7f0
f() return:1
p=0x7fff543fa7f0
p=0x7fff543fa7f0
f() return:1
p=0x7fff543fa7f0
p=0x7fff543fa7f0
f2() return:1
p=0x7fff543fa7f0
p=0x7fff543fa7f0
f2() return:1
p=0x7fff543fa7f0
p=0x7fff543fa7f0
f2() return:1

从打印结果可以看出,函数f和函数f2中的指针p指向的匿名对象的地址都相同。

函数f的作用域内,复合字面量"对象"是单例;

函数f2中,虽然匿名对象的地址也相同,但由于有while的块作用域,不一定匿名对象是单例,也可能恰好第一次循环分配的匿名对象释放了,然后第二次循环又在相同的地址上分配该匿名对象。

在C99标准中有这样一段话:

Each compound literal creates only a single object in a given scope.

Note that if an iteration statement were used instead of an explicit goto and a labeled statement, the lifetime of the unnamed object would be the body of the loop only, and on entry next time around p would have an indeterminate value, which would result in undefined behavior.

我暂时没有找到详细关于这段话的解释,只能通过实际的测试来验证,可能我上述的结论不一定正确。

接下来,看一个实际工程中使用复合字面量的例子

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))#define AV_FOURCC_MAX_STRING_SIZE 32
#define av_fourcc2str(fourcc) av_fourcc_make_string((char[AV_FOURCC_MAX_STRING_SIZE]){0}, fourcc)char *av_fourcc_make_string(char *buf, uint32_t fourcc)
{int i;char *orig_buf = buf;size_t buf_size = AV_FOURCC_MAX_STRING_SIZE;for (i = 0; i < 4; i++) {const int c = fourcc & 0xff;const int print_chr = (c >= '0' && c <= '9') ||(c >= 'a' && c <= 'z') ||(c >= 'A' && c <= 'Z') ||(c && strchr(". -_", c));const int len = snprintf(buf, buf_size, print_chr ? "%c" : "[%d]", c);if (len < 0)break;buf += len;buf_size = buf_size > len ? buf_size - len : 0;fourcc >>= 8;}return orig_buf;
}int main(int argc, char** argv)
{uint32_t type = MKTAG('r', 'o', 'o', 't');printf("%s\n", av_fourcc2str(type));return 0;
}

av_fourcc2str宏的作用是将以整型存储的4字符转换为字符串,其中使用了(char[AV_FOURCC_MAX_STRING_SIZE]){0},使代码更加的简洁。

复合字面量(compound literals)详解相关推荐

  1. 字面量(literal)与 C 语言复合字面量(compound literals)

    在计算机科学中,字面量(literal)是用于表达源代码中一个固定值的表示法(notation)(字面量是相对变量常量等定义的,无论是常量还是变量,其值在某一时刻总是确定的,只是变量可以反复赋值.刷新 ...

  2. ES6(一)——字面量的增强、解构、let/const、块级作用域、暂时性死区

    一.字面量的增强 ES6中对 对象字面量 进行了增强,称之为 Enhanced object literals(增强对象字面量). 字面量的增强主要包括下面几部分: 属性的简写:Property Sh ...

  3. 佳能c3020维修模式 白电平调整_佳能3020复合机电路及故障详解

    [IT168 使用技巧]CANON 佳能 NP-2020/3020/3100/3200/3300复印机故障码 E00定影故障码清除 关电源开关,拆下机器左侧后下边的调整盖;打开电源开关后按调整板上维修 ...

  4. c语言里字符串和字符串字面量,string literals(字符串字面量)

    构造一个指定字符数组类型的未命名对象,用于需要在源代码中嵌入字符串时使用. 句法 " s-char-sequence "(1)u8 " s-char-sequence & ...

  5. 用python刷网页浏览量_Python 刷点击量的代码详解

    [Python]代码 import webbrowser as web import re import urllib import time import os def spider(url,url ...

  6. c语言字面量的作用是为变量,C语言 字面量

    在计算机科学中,字面量(literal)是用于表达源代码中一个固定值的表示法(notation). 几乎所有计算机编程语言都具有对基本值的字面量表示,诸如:整数.浮点数以及字符串: 而有很多也对布尔类 ...

  7. python镜像下载包_python包详解

    干货大礼包!21天带你轻松学Python(文末领取更多福利) 点击查看课程视频地址 本课程来自于千锋教育在阿里云开发者社区学习中心上线课程<Python入门2020最新大课>,主讲人姜伟. ...

  8. python字符串处理编程实例_Python字符串处理实例详解

    干货大礼包!21天带你轻松学Python(文末领取更多福利) 点击查看课程视频地址 本课程来自于千锋教育在阿里云开发者社区学习中心上线课程<Python入门2020最新大课>,主讲人姜伟. ...

  9. Swin-Transformer网络结构详解

    文章目录 0 前言 1 网络整体框架 2 Patch Merging详解 3 W-MSA详解 MSA模块计算量 W-MSA模块计算量 4 SW-MSA详解 5 Relative Position Bi ...

最新文章

  1. 整理的16个有用的jQuery Form(表单)验证教程
  2. 工作一周了,紧张 + 累
  3. cocos2d-x 2.x创建帧序列动画
  4. 细说firewalld和iptables
  5. 正则满足中文的顿号_常用的正则表达式、正则表达式之断言
  6. pdf如何转换成word文档
  7. android mysql实现登录注册_android简单登陆和注册功能实现+SQLite数据库学习
  8. php GD库文字居中,PHP GD ttftext居中对齐
  9. ICCV 2019 | 商汤科技57篇论文入选,13项竞赛夺冠
  10. Introduction to Mathematical Thinking - Week 4
  11. java用1234组成_java编程题,java1234组成三位数不重复
  12. 玻利亚(Polya)的《怎样解题》
  13. 差分进化算法DE优化BPNN
  14. 垃圾分类催生创业公司
  15. Redis设置过期时间
  16. ESP8266恒温控制器
  17. ProcessingJoy —— 扭来扭去【JAVA】【GLSL】
  18. 亲测方案:解决HBuilder X启动提示语法助手无法访问的问题
  19. 阿里实习生电话面试总结
  20. 用Python做信号处理

热门文章

  1. [2023最新]美少妇Metasploit(MSF)下载安装及使用详解,永久免费使用,环境配置和使用技巧指南
  2. 数据可视化——R语言ggplot2包绘制相关矩阵为热图
  3. 固高GTS运动控制卡,C#语言三轴点胶机样本程序源代码,使用 的是固高GTS-800 8轴运动控制卡
  4. BTC菠萝B1 超高性价比 阿瓦隆1246现货 现货秒发
  5. synaptic在哪_在Ubuntu上需要Synaptic进行的10个软件包管理操作
  6. 微信插件第一讲之自动回复机器人(护妻宝)
  7. 来传智播客学到的知识
  8. Termux安装Linux及图形化教程
  9. 【架构师】零基础到精通——康威定律
  10. 010 Editor 9.0.2——注册错误(010 Editor has detected that you have entered an invalid license.)