C89,C99: C数组&结构体&联合体快速初始化
1. 背景
C89标准规定初始化语句的元素以固定顺序出现,该顺序即待初始化数组或结构体元素的定义顺序。
C99标准新增指定初始化(Designated Initializer),即可按照任意顺序对数组某些元素或结构体某些成员进行选择性初始化,只需指明它们所对应的数组下标或结构体成员名。GNU C将其作为C89模式的扩展。
借助指定初始化特性,可实现数组或结构体元素的快速初始化。
2. 数组初始化
在数组初始化列表中使用“[index常量表达式]=value”形式可对index所指定的某个元素进行初始化。如:
int arr[] = { []=, []=, [] =, []= }; 或
int arr[] = { []=, , [] =, }; 或
int arr[] = { [] =, , []=, }; (指定顺序可变)
均等效于:int arr[] = {, , , , , };
说明:
1) 若在某个指定初始化项目后跟有不至一个值,如[3]=10,11。则多出的数值用于对后续的数组元素进行初始化,即数值11用来初始化arr[4]。
2) C数组初始化一个或多个元素后,未初始化的元素将被自动地初始化为0或NULL(针对指针变量)。未经过任何初始化的数组,所有元素的值都是不确定的。
当下标是字符或属于枚举类型时,标识数组初始化语句的元素特别有用。如:
int whitespace[] = {
[' '] = , ['\t'] = , ['\h'] = ,
['\f'] = , ['\n'] = , ['\r'] = };
static const char* gMsgName[] = {
[MSG_CREATE] = "Create",
[MSG_DELETE] = "Delete",
[MSG_SET] = "Set",
[MSG_GET] = "Get",
[MSG_GET_ALARMS] = "GetAlarms",
[MSG_SET_TABLE] = "SetTable"}; //枚举值变化时,数组自动同步更新
这种初始化方式可实现简化的映射表,不过在下标指示符跨度较大时稍显浪费内存。
GNU C还支持”[first … last]=value”(…两侧有空格)的形式,将该范围内的若干元素初始化为相同值。如:
int arr[]={ [ ... ]=, [ ... ]=, [ ... ] =}; 或
int arr[]={ [ ... ]=, [ ... ]=, [ ... ] =, [] =};
均等效于:int arr[] = {, , , , , , , , , };
注意,数组长度为指定的最大下标值加1。
这种初始化方式比memset高效且用途更广,如:
int arr[]={ [ ... ]=- };
等效于:memset(arr, 0xFF, sizeof(arr));
int arr[]={ [ ... ]= };
不等效于:memset(arr, , sizeof(arr));
3. 结构体初始化
结构的指定初始化语法与数组类似,只不过使用点运算符和成员名(而不是方括号和索引值)标识具体的元素。例如,对于结构体
struct Structure{ int a; int b; };或struct Structure{ int a, b; };
有以下几种初始化方式:
struct Structure tStct = {
.a = ,
.b =
};
用“.fieldname=”指定待初始化成员名(成员初始化顺序可变)
struct Structure tStct = {
a : ,
b :
};
用“fieldname:”指定待初始化成员名(成员初始化顺序可变)
GCC .5已废除,但仍接受
struct Structure tStct = { , };
内核结构体多采用第一种初始化方式,如Linux-2.6.x/drivers/usb/storage/usb.c设备驱动程序中:
static struct usb_driver usb_storage_driver = {
.owner = THIS_MODULE,
.name = "usb-storage",
.probe = storage_probe,
.disconnect = storage_disconnect,
.id_table = storage_usb_ids,
};
该方式初始化时不必严格按照定义时的顺序,灵活性很高。
【例】定义如下结构体
struct book{
char title[MAXTITL];
char author[MAXAUTL];
float value;
int mask[];
};
可按照任意顺序使用指定初始化项目:
struct book gift = { .value = 25.99,
.author = "James Broadfool",
.title = "Rue for the Toad",
.mask[ ... ] = -};
也可只初始化结构体成员value:
struct book surprise = { .value = 10.99 };
正如数组一样,跟在指定初始化项目后且没有指示符(“[index]”或“fieldname”)的常规初始化项目为跟在指定成员后定义的下个成员提供初始值。此外,若对特定成员初始化多次,则最后一次赋值是它实际获得的值。
考虑下列声明:
struct book gift = { .value = 18.90,
.author = "Philionna pestle",
0.25};
将把值0.25赋给成员value,因为它在结构体定义中紧跟在author成员之后。新值0.25覆盖前值18.90。
若覆盖初始化有副作用(如类型不兼容),则GNU C可能会产生编译警告。
4 联合体初始化
可用“.fieldname” (或已废弃的“fieldname:”)指示符来指定使用联合体的哪个元素,如:
union UnionT { int i; double d; };
union UnionT tUnion = { .d = };
使用第二个元素将4转换为double类型存入联合体。相反,将4转换为union UnionT类型则会把它作为整数i存入联合体。
5 结构体数组初始化
可在“=”前写上一系列的“[index]”和“.fieldname”指示符来指定待初始化的嵌套子对象,如:
struct Structure ptStct[] = {
[].b = 0x2B, [].a = 0x2A,
[].a = 0x0A };
6 GCC扩展结构体赋值
对于上文定义的结构体Structure可整体赋值:
struct Structure tStct1, tStct2; tStct2 = tStct1;
结构体也可作为函数返回值对另一个结构体赋值:
struct Structure func1(); struct Structure tStct = func1();
C89,C99: C数组&结构体&联合体快速初始化的更多相关文章
- C数组&结构体&联合体快速初始化
背景 C89标准规定初始化语句的元素以固定顺序出现,该顺序即待初始化数组或结构体元素的定义顺序. C99标准新增指定初始化(Designated Initializer),即可按照任意顺序对数组某些元 ...
- C语言 结构体(联合体)对齐规则
/* 结构体(联合体)对齐规则 */ #include <stdio.h> #include <stdlib.h> #include <string.h> /* * ...
- c语言结构体指针必须初始化
先说结论 结构体指针需要初始化 结构体指针的成员指针同样需要初始化 结构体变量定义的时候就已经分配了内存空间,而上面两个确没有 struct test{ int i; struct buf *p;} ...
- go语言基础之结构体普通变量初始化
1.结构体 1.1.结构体类型 有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性.显然单独定义以上变量比较繁琐,数据不便于管理. 结构体是一种聚合的数 ...
- C++结构体成员列表初始化
C++关于struct和class的区别,可以看上一篇文章:c ++ class和struct[转] 结构体成员列表初始化,来个例子: #include <iostream> #inclu ...
- C语言基础(19)-结构体,联合体,枚举和typedef
一.结构体 1.1 结构体struct定义及初始化 #include <stdio.h> // 这个头文件在系统目录下 #include <stdlib.h> // 使用了sy ...
- C语言基础知识点整理(函数/变量/常量/指针/数组/结构体)
函数 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ...
- c++ 数组 结构体
接下来的一点时间我将会记录下我看的c++的一些心得体会,人贵在坚持,希望我可以一直坚持下去!!Go Fighting! 一.c++复合数据类型: 数组类型的一些注意事项: sizeof的用法: 当 ...
- Leetcode LRU缓存,数组+结构体实现
一.算法思路 LRUCache类有以下函数和变量: LRUCache(int capacity): capacity是当前对象能够存储的键值对(key,value)最大个数. int get(int ...
随机推荐
- Yii2数据库操作 事务
Yii2 DAO http://blog.csdn.net/hzqghost/article/details/44116039
- CSScomb.js --- 自定义 CSS 编写风格配置文件
一.排序分类 1. content overflow position z-index display float ... 表示定位/布局的属性(content比较特殊,作为伪元素不可少的,经常放置于 ...
- A*寻路算法C++简单实现
搜索区域 如图所示简易地图, 其中绿色方块的是起点 (用 A 表示), 中间蓝色的是障碍物, 红色的方块 (用 B 表示) 是目的地. 为了可以用一个二维数组来表示地图, 我们将地图划分成一个个 ...
- XSS漏洞的渗透利用另类玩法
XSS漏洞的渗透利用另类玩法 2017-08-08 18:20程序设计/微软/手机 作者:色豹 i春秋社区 今天就来讲一下大家都熟悉的 xss漏洞的渗透利用.相信大家对xss已经很熟悉了,但是很多安全 ...
- delete 和 splice 删除数组中元素的区别
delete 和 splice 删除数组中元素的区别 ` var arr1 = ["a","b","c","d"]; d ...
- AMS算法
#include<stdio.h> #include<stdlib.h> #include<time.h> #define N 1000//采样点的个数 #defi ...
- 剑指offer第二版面试题3:二维数组中的查找(JAVA版)
题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 1 2 8 9 2 4 ...
- java-day24
JDBC控制事务: 1.事务:一个包含多个步骤的业务操作,如果这个业务操作被事务管理,则这个步骤要么同时成功,要么同时失败. 2. 操作: 1. 开启事务 2. 提交事 ...
- java-day18
函数式接口在java中指:有且仅有一个抽象方法的接口 @FunctionalInterface注解:可以检测接口是否是一个函数式接口 函数式接口的使用:一般可以作为方法的参数和返回值类型 自定义函数式 ...
- 装机时键盘选择失误?教你修改kali Linux键盘到美式。
在Linux装机选择键盘的时候,由于学的是英式英语而选择了英式键盘,结果吃了大亏.英式键盘和我们平时使用的美式键盘的键位是不一样的! 这是我们平时使用的美式键盘: 这是英式键盘: 修改的方式是: 点击 ...