背景

C89标准规定初始化语句的元素以固定顺序出现,该顺序即待初始化数组或结构体元素的定义顺序。

C99标准新增指定初始化(Designated Initializer),即可按照任意顺序对数组某些元素或结构体某些成员进行选择性初始化,只需指明它们所对应的数组下标或结构体成员名。GNU C将其作为C89模式的扩展。

借助指定初始化特性,可实现数组或结构体元素的快速初始化。

数组初始化

在数组初始化列表中使用“[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));

结构体初始化

结构的指定初始化语法与数组类似,只不过使用点运算符和成员名(而不是方括号和索引值)标识具体的元素。例如,对于结构体

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);

联合体初始化

可用“.fieldname” (或已废弃的“fieldname:”)指示符来指定使用联合体的哪个元素,如:

union UnionT { int i; double d; };

union UnionT tUnion = { .d = 4 };

使用第二个元素将4转换为double类型存入联合体。相反,将4转换为union UnionT类型则会把它作为整数i存入联合体。

结构体数组初始化

可在“=”前写上一系列的“[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数组&结构体&联合体快速初始化的更多相关文章

  1. C89,C99: C数组&结构体&联合体快速初始化

    1. 背景 C89标准规定初始化语句的元素以固定顺序出现,该顺序即待初始化数组或结构体元素的定义顺序. C99标准新增指定初始化(Designated Initializer),即可按照任意顺序对数组 ...

  2. c语言结构体指针必须初始化

    先说结论 结构体指针需要初始化 结构体指针的成员指针同样需要初始化 结构体变量定义的时候就已经分配了内存空间,而上面两个确没有 struct test{ int i; struct buf *p;} ...

  3. C语言 结构体(联合体)对齐规则

    /* 结构体(联合体)对齐规则 */ #include <stdio.h> #include <stdlib.h> #include <string.h> /* * ...

  4. go语言基础之结构体普通变量初始化

    1.结构体 1.1.结构体类型 有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性.显然单独定义以上变量比较繁琐,数据不便于管理. 结构体是一种聚合的数 ...

  5. C++结构体成员列表初始化

    C++关于struct和class的区别,可以看上一篇文章:c ++ class和struct[转] 结构体成员列表初始化,来个例子: #include <iostream> #inclu ...

  6. C语言基础(19)-结构体,联合体,枚举和typedef

    一.结构体 1.1 结构体struct定义及初始化 #include <stdio.h> // 这个头文件在系统目录下 #include <stdlib.h> // 使用了sy ...

  7. C语言基础知识点整理(函数/变量/常量/指针/数组/结构体)

    函数 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ...

  8. c++ 数组 结构体

    接下来的一点时间我将会记录下我看的c++的一些心得体会,人贵在坚持,希望我可以一直坚持下去!!Go Fighting!   一.c++复合数据类型: 数组类型的一些注意事项: sizeof的用法: 当 ...

  9. Leetcode LRU缓存,数组+结构体实现

    一.算法思路 LRUCache类有以下函数和变量: LRUCache(int capacity): capacity是当前对象能够存储的键值对(key,value)最大个数. int get(int ...

随机推荐

  1. core 文件查看

    步骤: (1)无论你是用Makefile来编译,还是直接在命令行手工输入命令来编译,都应该加上 -g 选项. (2)一般来说,在默认情况下,在程序崩溃时,core文件是不生成的(很多Linux发行版在 ...

  2. swing包含了各种组件的类

    javax.swing 最常用的pachage,包含了各种swing组件的类 javax.swing.border 包含与swing组件外框有关的类 javax..swing.colorchooser ...

  3. ARM mbed平台WIZwiki-W7500使用说明

    ARM mbed IDE 是ARM内核微控制器的在线开发工具,其站点是:http://developer.mbed.org. 站点提供了在线编译器,不须要本地安装编译器就可以进行开发,因此没有地点.时 ...

  4. ckeditor4.2.1常用配置

    常用的配置信息都放在根目录的config.js文件中,一些常用的配置项如下: 1.界面语言 //语言 config.language = 'zh-cn'; 2.字体添加中文 //字体 config.f ...

  5. tracert

    TRACERT命令 编辑 Tracert(跟踪路由)是路由跟踪实用程序,用于确定 IP数据包访问目标所采取的路径.Tracert 命令使用用 IP 生存时间 (TTL) 字段和 ICMP 错误消息来确 ...

  6. c#中//注释和///注释的区别 智能注释 显示换行

    ///会被编译,//不会所以使用///会减慢编译的速度(但不会影响执行速度)///会在其它的人调用你的代码时提供智能感知 也是一种注释,但是这种注释主要有两种作用:1.这些注释能够生成一个XML文件. ...

  7. C# Byte[]、Image、Bitmap 之间的相互转换

    //byte[] 转图片 public static Bitmap BytesToBitmap(byte[] Bytes) { MemoryStream stream = null; try { st ...

  8. 分布式缓存系统 Memcached 整体架构

    分布式缓存系统 Memcached整体架构 Memcached经验分享[架构方向] Memcached 及 Redis 架构分析和比较

  9. 基于maven使用IDEA创建多模块项目

    原文地址:http://blog.csdn.net/williamhappy/article/details/54376855 鉴于最近学习一个分布式项目的开发,讲一下关于使用IntelliJ IDE ...

  10. 【QT学习】QT GUI应用程序的框架,文件分析

    有几个名字,项目名,类名,界面对象名. 1.项目文件 项目名.pro(MyHelloQt.pro) 主要包括项目用到的模块,项目包含哪些源码文件,头文件,窗体文件,生成应用程序的名称. 由QT自动生成 ...