C数组&结构体&联合体快速初始化
背景
C89标准规定初始化语句的元素以固定顺序出现,该顺序即待初始化数组或结构体元素的定义顺序。
C99标准新增指定初始化(Designated Initializer),即可按照任意顺序对数组某些元素或结构体某些成员进行选择性初始化,只需指明它们所对应的数组下标或结构体成员名。GNU C将其作为C89模式的扩展。
借助指定初始化特性,可实现数组或结构体元素的快速初始化。
1 数组初始化
在数组初始化列表中使用“[index常量表达式]=value”形式可对index所指定的某个元素进行初始化。如:
int arr[6] = { [0]=5, [1]=6, [3] =10, [4]=11 }; 或 int arr[6] = { [0]=5, 6, [3] =10, 11 }; 或 int arr[6] = { [3] =10, 11, [0]=5, 6 }; (指定顺序可变) 均等效于:int arr[6] = {5, 6, 0, 10, 11, 0}; |
说明:
1) 若在某个指定初始化项目后跟有不至一个值,如[3]=10,11。则多出的数值用于对后续的数组元素进行初始化,即数值11用来初始化arr[4]。
2) C数组初始化一个或多个元素后,未初始化的元素将被自动地初始化为0或NULL(针对指针变量)。未经过任何初始化的数组,所有元素的值都是不确定的。
当下标是字符或属于枚举类型时,标识数组初始化语句的元素特别有用。如:
int whitespace[256] = { [' '] = 1, ['\t'] = 1, ['\h'] = 1, ['\f'] = 1, ['\n'] = 1, ['\r'] = 1 }; 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[]={ [0 ... 3]=1, [4 ... 5]=2, [6 ... 9] =3}; 或 int arr[]={ [0 ... 3]=1, [4 ... 5]=2, [6 ... 8] =3, [9] =3}; 均等效于:int arr[10] = {1, 1, 1, 1, 2, 2, 3, 3, 3, 3}; |
注意,数组长度为指定的最大下标值加1。
这种初始化方式比memset高效且用途更广,如:
int arr[]={ [0 ... 127]=-1 }; 等效于:memset(arr, 0xFF, sizeof(arr)); int arr[]={ [0 ... 127]=1 }; 不等效于:memset(arr, , sizeof(arr)); |
2 结构体初始化
结构的指定初始化语法与数组类似,只不过使用点运算符和成员名(而不是方括号和索引值)标识具体的元素。例如,对于结构体
struct Structure{ int a; int b; };或struct Structure{ int a, b; };
有以下几种初始化方式:
struct Structure tStct = { .a = 1, .b = 2 }; 用“.fieldname=”指定待初始化成员名(成员初始化顺序可变) |
struct Structure tStct = { a : 1, b : 2 }; 用“fieldname:”指定待初始化成员名(成员初始化顺序可变) GCC 2.5已废除,但仍接受 |
struct Structure tStct = { 1, 2}; |
内核结构体多采用第一种初始化方式,如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[128]; }; |
可按照任意顺序使用指定初始化项目:
struct book gift = { .value = 25.99, .author = "James Broadfool", .title = "Rue for the Toad", .mask[0 ... 127] = -1}; |
也可只初始化结构体成员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可能会产生编译警告。
利用指定初始化特性,可方便地编写如下的测试例程:
AGENT_PW_PSN tPwPsn = { .dwSlotNo = 2, .dwPortNo = dwPortNo, .dwPsnType = TRANS_MPLS, .dwInBndLable = dwInBndLable, .dwOutBndLable = dwOutBndLable, .dwMplsType = MPLS_SINGLE_LABELLED, .dwInBndTunnelLable = 0, .dwOutBndTunnelLable = 0, .aucDstMac = {0x00,0x15,0xeb,0x72,0x00,0x0e}, .dwVlanId = 300, .dwPriority = 7 }; OmciSetPwPsn(&tPwPsn, sizeof(tPwPsn), aucBufOut, &dwOutLen); |
3 联合体初始化
可用“.fieldname” (或已废弃的“fieldname:”)指示符来指定使用联合体的哪个元素,如:
union UnionT { int i; double d; }; union UnionT tUnion = { .d = 4 }; |
使用第二个元素将4转换为double类型存入联合体。相反,将4转换为union UnionT类型则会把它作为整数i存入联合体。
4 结构体数组初始化
可在“=”前写上一系列的“[index]”和“.fieldname”指示符来指定待初始化的嵌套子对象,如:
struct Structure ptStct[10] = { [2].b = 0x2B, [2].a = 0x2A, [0].a = 0x0A }; |
5 GCC扩展结构体赋值
对于上文定义的结构体Structure可整体赋值:
struct Structure tStct1, tStct2; tStct2 = tStct1; |
结构体也可作为函数返回值对另一个结构体赋值:
struct Structure func1(); struct Structure tStct = func1(); |
C数组&结构体&联合体快速初始化的更多相关文章
- C89,C99: C数组&结构体&联合体快速初始化
1. 背景 C89标准规定初始化语句的元素以固定顺序出现,该顺序即待初始化数组或结构体元素的定义顺序. C99标准新增指定初始化(Designated Initializer),即可按照任意顺序对数组 ...
- c语言结构体指针必须初始化
先说结论 结构体指针需要初始化 结构体指针的成员指针同样需要初始化 结构体变量定义的时候就已经分配了内存空间,而上面两个确没有 struct test{ int i; struct buf *p;} ...
- C语言 结构体(联合体)对齐规则
/* 结构体(联合体)对齐规则 */ #include <stdio.h> #include <stdlib.h> #include <string.h> /* * ...
- 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 ...
随机推荐
- Java EE的十三个技术规范
Java 是一种非常棒的语言,健壮,跨平台运行,屏蔽了具体的平台环境的要求,也就是说只要支持java 虚拟机,就可以运行java程序. 下面,我们一起学习一下J2EE的十三种技术规范. 一.JDBC: ...
- WinForm控件学习笔记【第一天】——Control类
感悟:明天就又是学校双选会的日子了.两年我都参与了学校的双选会的服务工作,现在该是双选会服务的我时候了.怎么样找到一份好的工作,或者说怎么样学习才能符合企业对人才的要求,我现在也是很迷茫.平时都是在看 ...
- Hadoop分布式集群部署(单namenode节点)
Hadoop分布式集群部署 系统系统环境: OS: CentOS 6.8 内存:2G CPU:1核 Software:jdk-8u151-linux-x64.rpm hadoop-2.7.4.tar. ...
- ping失败的结果分析
①Request timed out 这是大家经常碰到的提示信息,很多文章中说这是对方机器置了过滤ICMP数据包,从上面工作过程来看,这是不完全正确的,至少有下几种情况. a. 对方已关机,或者网络上 ...
- log4net 日志配置及使用
一.log4net按照不同的[LEVEL]级别输出到不同文件 <log4net> <!--错误日志:::记录错误日志--> <!--按日期分割日志文件 一天一个--> ...
- mysql的字符串函数
From: http://www.cnblogs.com/xiaochaohuashengmi/archive/2010/12/13/1904330.html 对于针对字符串位置的操作,第一个位置被标 ...
- Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点
上一篇分享了 Nginx + Tomcat 反向代理 负载均衡 集群 部署指南,感觉还是相当实用型的,但是一般集群部署是基于大访问量的,可能有的企业用不到,类似一些企业官网,访问量并不是很大,基于这个 ...
- Linux 下 Nginx 反向代理 负载均衡配置
转载请注明出处:http://blog.csdn.net/smartbetter/article/details/52036350 上一篇分享了 Nginx + JDK + Tomcat + MySQ ...
- mysql执行SQL语句时报错:[Err] 3 - Error writing file '/tmp/MYP0G1B8' (Errcode: 28 - No space left on device)
问题描述: 今天一同事在mysql中执行SQL语句的时候,报了/tmp空间不足的问题,报错如下: [SQL] SELECT f.prov as 字段1, MAX( CASE f.flag_name W ...
- 修复日志,阻止给日志多次添加handlers时候重复打印的问题
1.解决如果多次添加handlers重复打印的问题.在__add_handlers方法中作出判断. 2.由get_logger_and_add_handlers和get_logger_without_ ...