C语言中匿名的最高境界

ddfadf4f31d70c52a3136690edb3d812.jpeg

C语言中有没有见过(int [2]){19,20}或者int (*pt2)[4]的使用方法,字面上可能不好理解,这是C99之后才新增的知识点,名为复合型表述Compound Literals,一旦熟悉使用,便会体会到它简洁而强大的表达。

什么是”复合型表述“?

假设给带int类型的形参函数传递一个值,可以传递int类型的变量,也可以传递int类型常量,但是对于带数组形参的函数则不一样,可以传递数组,但是不支持传递数组常量,由此C99新增了“复合形表述”的用法,“表述(Literals)”是指除符号常量外的常量。

例如10是一种int的类型的表述,10.24是一种double类型的表述,“lixiaoyao”是一种字符串类型的表述等——这些都是关于单个类型常量值的表述。自然而然的,对于数组或者结构体这种内部存在多个成员的数据类型,其关于常量的表述就叫做复合型表述。

关于数组的复合型表述

数组的复合型表述和数组初始化列表差不多,前面使用括号括起来的类型名,例如下面是一个普通的数组声明。

int age[2]=[19,20];

下面创建了一个和age数组相同的匿名数组,也有两个int类型值。

(int [2]){19,20}; //复合型表述

注意去掉申明中的数组名,留下的int[2]就是复合型表述的类型名。

初始化有数组名的数组可以省略数组的大小,复合型表述也可以省略大小,编译器会自动计算数组当前的元素个数:

(int []){19,20,21,22,23}//内含5个元素的复合型表述

因为复合型表述是匿名的,所以不能先创建然后再使用它,必须在创建的同时使用它,如下:

int x;
// 正确
x = 100;int arr[1];
// 错误
arr = {0};

一般需要这样定义使用:

int *pt1;
pt1=(int[2]){19,20};

注意,该复合型表述的字面常量与上面创建age数组的表述量完全相同,复合型表述的类型名也代表着首元素的地址,所以可以把它赋给指向int的指针。

作为实际参数

复合型表述作为实际参数传递给带有匹配形式参数的函数。

#include <stdio.h>
int sum(const int age[],int n);int main () {int total;total =sum((int[]){4,4,4,5,5,5},6);return 0;
}int sum(const int age[],int n){int i=0;for(i=0;i<n;i++){printf("age is %d\n",age[i]);}
}

输出结果如下:

047d4423f6233ad274a0dc7f066e33e0.png

应用于二维数组或者多维数组

这种用法还可以应用于二维或者多维数组,例如下面演示了如何创建二维int数组并存储其地址。

int (*pt2)[4];
//申明一个指向二维数组的指针,该数组内有2个数组元素
//每个元素是内含4个int类型值的数组
pt2 = (int [2][4]) {{1,2,3,4,},{5,6,7,8,}};

对于结构体

假设如下所示声明了struct foo和structure:

struct foo {int a; char b[2];
} structure;

这是使用复合型表述构造struct foo的示例:

structure = ((struct foo) {x + y, 'a', 0});

这等效于以下代码:

{struct foo temp = {x + y, 'a', 0};structure = temp;
}

也可以构造一个数组,如下所述,如果复合型表述的所有元素都是由简单的常量表达式组成,则可以将复合型表述强制转换为指向其第一个元素的指针,并在此类初始化程序中使用, 如下所示:

char **foo = (char *[]) { "x", "y", "z" };

标量类型和联合类型的复合型表述也被允许,在下面的示例中,变量i初始化为值2,该值是由复合型表述创建的未命名对象递增的结果。

int i = ++(int){1};

作为GNU扩展,GCC允许通过复合型表述初始化具有静态存储持续时间的对象,如果复合型表述和对象的类型匹配,则如同仅使用括号括起来的列表初始化对象一样处理该对象,复合型表述的元素必须是常量。如果要初始化的对象具有未知大小的数组类型,则该大小由复合型表述的大小确定。

static struct foo x = (struct foo) {1, 'a', 'b'};
static int y[] = (int []) {1, 2, 3};
static int z[] = (int [3]) {1};

等效于以下内容:

static struct foo x = {1, 'a', 'b'};
static int y[] = {1, 2, 3};
static int z[] = {1, 0, 0};

C/C++中的区别

复合型表述看起来像是用括号括起来的聚合初始化程序列表的强制转换,它的值是强制类型转换中指定类型的对象,其中包含初始化程序中指定的元素。

与强制转换的结果不同,复合型表述是左值,但是 C++ 中目前还没有这种无名左值,作为扩展,GCC在C90模式和C++中也支持复合型表述,但C++语义有所不同。

在C中,复合型表述表示具有静态或自动存储持续时间的未命名对象;在C++中,复合型表述表示一个临时对象,该对象仅在其完整表达式结束之前一直存在。

所以,定义良好的C代码(采用复合型表述的子对象的地址)可以在C++中未定义,因此g++编译器不能将临时数组转换为指针。

例如,如果上面的数组复合型表述示例出现在函数内部,则C++中对foo的任何后续使用都将具有未定义的行为,因为数组的生存期在声明foo之后结束。

作为一种优化,g++编译器有时会给数组复合型表述提供更长的生存期:当数组出现在函数外部或具有const限定类型时。如果foo及其初始化程序的元素类型为char * const而不是char *,或者foo为全局变量,则该数组将具有静态存储持续时间。

参考:https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html

END

作者:李肖遥

来源:技术让梦想更伟大


版权归原作者所有,如有侵权,请联系删除。

3c0d575ef0537c66f101ca95889bed62.jpeg

766aa1b46890ef0886e6463c86b07cd3.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/463621.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

类与对象(C++)

2.1 类与对象2.1.1 结构体2.1.2 类 2.1 类与对象 2.1.1 结构体 C中的结构体不仅可以包含不同类型的数据&#xff0c;而且还可以包含操作这些数据的函数。 #include <iostream> using namespace std;struct Complex{double i;double r;void init(double rr, double ii)…

Mysql数据库的分离和附加转

一.MYSQL的命令行模式的设置&#xff1a;桌面->我的电脑->属性->环境变量->新建->PATH“&#xff1b;path/mysql/bin;”其中path为MYSQL的安装路径。二.简单的介绍一下命令行进入MYSQL的方法&#xff1a;1.C:/>mysql -h hostname -u username -p 按ENTER键&a…

Python中的xxx+=xxx和xxx=xxx+xxx一些区别及执行过程

预知小知识&#xff1a; Python中的变量与其他语言稍有差异&#xff0c;如a 10并不是直接在内存中创建一个变量a其值为10&#xff0c;而是在内存中创建一个a这个a指向这个10&#xff0c;在Python中所有牵扯到等号的均不是值赋值&#xff0c;全都是引用(C的小伙伴可以大致理解为…

codeblocks安装后提示找不到编译器

安装了自带编译器的codeblocks&#xff0c;但是打开后提示没有找到compiler&#xff0c; 经过几分钟的搜索&#xff0c;找了原因&#xff1a; 打开codeblocks&#xff0c;进入settings->compiler&#xff0c;选择如下: 然后&#xff0c;选择Toolchain executables&#xff…

欢迎加入Hello China技术讨论群组-QQ群:38467832

欢迎加入Hello China技术讨论群组-QQ群&#xff1a;38467832 在此群组内&#xff0c;我们可一起讨论Hello China及其它嵌入式操作系统的技术问题、应用问题以及其它相关问题。 Hello China相关的技术文档和实现文章&#xff0c;也会首先在该群组内发布给群内朋友。 转载于:http…

一文读懂|栈溢出攻击

什么是栈简单来说&#xff0c;栈 是一种 LIFO&#xff08;Last In Frist Out&#xff0c;后进先出&#xff09; 形式的数据结构。栈一般是从高地址向低地址增长&#xff0c;并且栈支持 push&#xff08;入栈&#xff09; 和 pop&#xff08;出栈&#xff09; 两个操作。如下图所…

用来做 favicon 的站点

这个站点是最好用的 http://converticon.com/转载于:https://www.cnblogs.com/johnsonshu/archive/2012/06/28/2568530.html

Codeforces Round #533 (Div. 2) C.思维dp D. 多源BFS

题目链接&#xff1a;https://codeforces.com/contest/1105 C. Ayoub and Lost Array 题目大意&#xff1a;一个长度为n的数组&#xff0c;数组的元素都在[L,R]之间&#xff0c;并且数组全部元素的和可以被3整除&#xff0c;问有多少种方法构建出该数组。答案模1000000007 例 输…

c++并发编程之原子操作的实现原理

原子(atomic)本意是”不能被进一步分割的最小粒子”,而原子操作(atomic operation)意为”不可被中断的一个或一系列操作”. 处理器如何实现原子操作 (1) 使用总线锁保证原子性 如果多个处理器同时对共享变量进行读写操作,那么共享变量就会被多个处理器同时进行操作,这样读写…

Sqlserver 通用存储过程(二) 联合主键

CREATEPROCP_public_ViewPage /**//**//**//* no_mIss 通用分页存储过程 2007.3.1 QQ:34813284 适用于联合主键/单主键/存在能确定唯一行列/存在能确定唯一行的多列 (用英文,隔开) 调用&#xff1a; 第一页查询时返回总记录和总页数及第一…

PHP定时执行任务的实现

此代码只要运行一次后关闭浏览器即可。 ignore_user_abort();//关掉浏览器&#xff0c;PHP脚本也可以继续执行.set_time_limit(0);// 通过set_time_limit(0)可以让程序无限制的执行下去$interval60*30;// 每隔半小时运行do{//这里是你要执行的代码sleep($interval);// 等待5分钟…

预检请求

不久前在公司写了一个基于 Hapijs 的后端项目&#xff0c;感觉这个框架很有自己的特点&#xff0c;跟 Express 和 Koa 的区别比较大&#xff0c;体现了配置大于编码的思想。用起来很方便&#xff0c;据说 Walmart 团队用这个框架扛住了黑五的流量&#xff0c;看起来在实际项目中…

linux编译动态库之-fPIC

在生成动态库时&#xff0c;常常习惯性的加上fPIC选项&#xff0c;fPIC有什么作用和意义&#xff0c;加不加有什么区别&#xff0c;这里做下小结&#xff1a; fPIC的全称是 Position Independent Code&#xff0c; 用于生成位置无关代码。什么是位置无关代码&#xff0c;个人理…

深入理解golang 的栈

线程栈(thread stacks)介绍 先回顾下linux的内存空间布局 简书_stack02.png当启动一个C实现的thread时&#xff0c;C标准库会负责分配一块内存作为这个线程的栈。标准库分配这块内存&#xff0c;告诉内核它的位置并让内核处理这个线程 的执行。在linux系统中&#xff0c;可通过…

const和define的区别

今天查看以前的代码&#xff0c;进行优化&#xff0c;回想到const和define一些区别&#xff0c;记录下来。 1.const是关键字&#xff0c;define不是关键字。 2.const定义的是只读变量&#xff0c;不是常量&#xff0c;define宏定义的是常量&#xff0c;变量不能作为定义数组的维…

理解ALSA

最近处理音频的问题&#xff0c;所以看了一些不错的文章&#xff0c;整理一些有用的资料出来&#xff0c;有需要的可以收藏。ALSA的框架图&#xff1a;这个图可以说是我目前看到最不错的&#xff0c;我发现很多应用开发的&#xff0c;一出现解决不了的问题&#xff0c;或者奇怪…

Xshell 6如何设置多个session显示在同一个窗口

刚才安装了Xshell 6之后&#xff0c;发现在同一个窗口只能显示4个session&#xff0c;网上查找了一些资料但是都不是想要的结果&#xff0c;经过几分钟的查找&#xff0c;终于找到了设置在同一个窗口session的个数&#xff0c;因此记录下来&#xff0c;或者给与他人帮助。以下以…

appium+java(五)微信小程序自动化测试实践

前言&#xff1a; 上一篇《appiumjava&#xff08;四&#xff09;微信公众号自动化测试实践》中&#xff0c;尝试使用appium实现微信公众号自动化测试&#xff0c;接着尝试小程序自动化&#xff0c;以学院小程序为例 准备工作 1、java-client 3.4.16依赖包 2、微信应用版本7.0.…

blockUI应用到Asp.Net页面时服务器控件(Button等)失效的问题

问题&#xff1a;在Asp.Net页面中用blockUI这个控件实现弹出窗口的效果&#xff0c;弹出页面内容为页面中某个Panel中的内容&#xff0c;包含TextBox、Button等服务器控件。使用时就简单的设置message属性。问题出来了&#xff0c;当显示这个弹出页面后&#xff0c;所有Button等…

android DatePicker

为什么80%的码农都做不了架构师&#xff1f;>>> public class DatePicker extends FrameLayout java.lang.Object android.view.View android.view.ViewGroup android.widget.FrameLayout android.widget.DatePicker DatePicker 一个选择年月日的日历布局视图 公…