zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C语言面试干货——指定数组初始化器(GCC手册解析)

C语言数组面试 解析 指定 手册 初始化 干货
2023-09-14 09:13:08 时间

本人就职于国际知名终端厂商,负责modem芯片研发。
在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。

指定数组初始化器(Designated Initializers)

背景

在ISO C90中,初始化数组或者结构体要求每个元素按照固定的顺序出现,带来的问题就是如果我们想初始化数组或结构体中的某个元素,那我们必须也手动初始化这个元素之前的元素。

在ISO C99中,你可以使用数组下标或者结构体的成员名实现乱序初始化,并且GNU C对这个功能进行了扩展,使得在C90中也可以使用。

初始化数组

int a[6] = { [4] = 29, [2] = 15 };
//等价于C90中的
int a[6] = { 0, 0, 15, 0, 29, 0 };

再看一个例子

#include<stdio.h>

int main(void)
{
	int a[]={0,1,2,3,[2]=5,6,9,10};
	
	printf("size is %zd\n",sizeof(a)/sizeof(int)); 
	for(int i=0;i<sizeof(a)/sizeof(int);++i)
		printf("%d ",a[i]); 
	
	return 0;
}

输出如下:
在这里插入图片描述
看到这里有些同学蒙了,为什么size is 6?为什么[3]=6而不是3?

我们通过下图进行解释:
在这里插入图片描述
当初始化指针重置回index=2的位置后,后面的初始化工作会基于重置后的位置继续完成,所以index=3的值初始化为6(原始值为3)

再看下面这段code

#include<stdio.h>

int main(void)
{
	int a[]={0,1,2,3,[7]=5,6,9,10};

	printf("size is %zd\n",sizeof(a)/sizeof(int)); 
	for(int i=0;i<sizeof(a)/sizeof(int);++i)
		printf("%d ",a[i]); 
	
	return 0;
}

输出为:
在这里插入图片描述
这个例子中我们并没有明确初始化数组a的index=4,5,6位置的值,这种情况下编译器会将其初始化为0


初始化指定范围的数组元素

这不是标准C中的功能,时GNU的一个扩展功能,使用 [first … last] = value的格式进行初始化,例如

/* [first ... last] = value 注意"..."与first和last之间的空格 */
/* 漏掉空格编译器会报错 */
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };

上面的code将数组widths的index=0-9初始化为1,index=10-99初始化为2,index=100初始化为3

看下面这段code

#include<stdio.h>

int main(void)
{
	int a[]={[0 ... 7]=5,6,[2]=9,10};
	
	printf("size is %zd\n",sizeof(a)/sizeof(int)); 
	for(int i=0;i<sizeof(a)/sizeof(int);++i)
		printf("%d ",a[i]); 
	
	return 0;
}

输出如下:
在这里插入图片描述
产生这样输出结果的原因与上面的原因一样,同学们自行理解。

在这里插入图片描述
上面的例子数组长度都是编译器负责计算的,下面我们看一个例子,这个例子中我们自行指定数组的长度:

int a[6] = { [1] = v1, v2, [4] = v4 };
//等价于
int a[6] = { 0, v1, v2, 0, v4, 0 };

在明确指定了长度的数组中,我们未初始化的元素编译器会帮我们进行初始化为0。

对于自动存储类型的数组,如果我们没有任何一个元素进行初始化,则整个数组的值都是未定义的;

对于自动存储类型的数组,如果我们初始化了一个或以上的元素,则其余未初始化的元素编译器会自动帮我们初始化为0。


C语言面试干货——指定结构体初始化器(GCC手册解析)


在这里插入图片描述