详解C语言结构和联合

结构体基础

聚合类型——能够同时存储超过一个单独的数据,C语言提供两种聚合数据类型数组结构
数组和结构的区别:

  • 数组是相同类型的数据的聚合,结构是不同类型数据的聚合;
  • 因为数组的元素长度相同可以采用下标方式访问,结构成员的长度不同,只能通过名字访问,不能通过下标来访问。
  • 数组名在表达式中使用时被当做一个指针,而结构体变量在表达式中使用时不能被当做一个指针。

我们可以声明指向结构的指针,取一个结构变量的地址以及声明结构数组

结构体变量的声明

struct tag 
{
  number_list;
} variable_list;

其中tag可以省略,但这样的话只能声明一个结构体变量,tag用来声明多个相同的结构体变量。

标签允许多个声明使用同一个成员列表,并且创建同一种类型的结构,标签只标识了一种模式,用于声明未来标变量。

struct stInfo
{
  int age ;
 char name[];
  int classNo; 
}
  /* 这个声明只是把stInfo和这个成员列表关联起来,但是没有创建任何结构变量*/
struct stInfo info; //声明结构体变量info
struct stInfo *info1; //声明指向结构体变量的指针
struct stInfo inf2[]; //声明指向结构体的数组
  /*info info1 info2都是同一种类型的结构体*/

声明结构可以使用另外一种良好的技巧是用type创建一种新的类型如下面的例子所示:

type struct
{
  int a;
  char b;
  float c;
} stSimple; //注意最后是有分号(;)的

/*stSimple是一个类型名,而不是一个变量名*/
stSimple x; 
stSimple y[];
stSimple *z;

结构体成员

结构体里面可以声明任何类型的变量作为结构体的成员,像结构,体联合体等;

struct COMPLEX
{
  float f;
  int a [20];
  long *lp;
  struct stSimple s;
  struct stSimple sa[20];
  struct stSimple *sp;
}

一个结构体的成员名字和其他结构的成员名字相同,所以这个结构的成员a并不会与struct stSimple s的成员a冲突。

结构体成员变量的直接访问

结构体变量的成员是通过操作符(.),点操作符接受两个操作数,左操作数是结构体变量的名字,右操作数是结构体变量的成员,点操作符是自左向右*的结合性。

struct COMPLEX comp;
comp.f; //访问成员f
comp.s.a //访问嵌套结构体成员a
comp.a[4] //访问结构体数组成员
comp sa[4].c //访问结构体数组成员

结构体成员的间接访问

当拥有一个指向结构体变量的指针,当使用这个指针访问结构体成员时就是结构体成员的间接访问
  结构体成员的间接访问使用箭头操作符(——>),该操作符的左操作数是一个指向结构体的指针,右操作数是结构体成员

struct COMPLEX *compp;
compp->f;
compp->a[1];
compp->s.a;
compp->sa[4].c;
compp->sp->b;

结构体变量的自引用

先看一个结构体违法自引用的例子:

struct SELF_RIF1
{
  int a;
  struct  SELF_RIF1 b; //嵌套一个结构体
  int c;
}

这种引用是违法的,因为成员b是另一个完整的结构体,其内部还包括自己的成员b,如此往复循环无穷尽。
  再看合法的结构体自引用

struct SELF_RIF1
{
  int a;
  struct  SELF_RIF1 *b; //嵌套一个结构体
  int c;
}

这个 声明和前面那个的区别在于b现在是一个指针而不是一个结构。编译器在结构的长度确定之前就已经知道指针的长度,所以这种类型的自引用是合法的。

事实上一个结构内部包含一个指向该结构本身的指针,它事实上所指向的是同一种类型的不同结构,链表和树都是用这种技巧实现的,每个结构指向链表的下一个元素或树的下一个分支。

结构的初始化

结构的初始化方式和数组的初始化很类似——一个位于一对花括号内部,由逗号分隔的初始列表可用于结构各个成员的初始化,这些值根据结构成员的顺序写出。如果初始列表的值不够,剩余的结构成员将使用缺省值进行初始化。
  结构中如果包含数组和结构成员,其初始化方式类似于多维数组的初始化。

struct INIT_EX
{
  int a;
  short b[10];
  Simple c;
} x = {
  10,
  {1,2,3,4,5},
 { 25,'x',1.9}
};

作为函数参数的结构

结构是一个标量,它可以用于其它标量可以使用的任何场合,因此把结构作为一个参数传递给一个函数是合法的。

给函数传递指向结构的指针的效率要远大于向函数传递整个结构。

typedef struct
{
  char product[PRODUCT_SIZE];
  int quantity;
  float unit_price;
  float total_amount;
} Transaction;
/函数参数为整个结构的版本/
void print_receipt(Transaction trans)
{
  ...
}
/函数参数为指向结构的指针版本/
void print_receipt(Transaction *trans)
{
  ...
}
/分别定义结构和指向结构的指针并调用函数/
 Transaction current_trans;
  print_receipt(current_trans);  //调用函数参数为整个结构的版本
  print_receipt(&current_trans); //调用函数参数为指向结构指针的版本

向函数传递指向结构的指针和向函数传递整个结构相比效率会很高,且结构越大这种优势越明显。

联合

联合和结构相似,但它的行为和结构不一样。联合的所有的成员引用的是内存中的相同位置

 union 
{
  float f;
  int i;
} fi;

在一个浮点型和整型都是32位的机器上,变量fi只占用内存中一个32位的字,如果成员f被使用,这个字就被作为浮点值访问,如果成员i被使用,这个字就被当作整型值访问。

联合在某一时刻只能有一个成员被访问,如果联合成员的长度不一样,联合的长度就是它最长成员的长度,若长度悬殊特别大,可以在联合中存储指向不同成员的指针而不是直接存储成员本身,所有指针的长度都相同。

联合的初始化

联合变量可以被初始化,但这个值必须是联合的第一个成员的类型,而且它必须位于一堆花括号里面,例如:

union
{
  int a;
  float f;
  char c[4];
} x = {5};

我们不能把这个类变量初始化为一个浮点数或字符值,如果给出的初始值是任何其它类型,它就会转换为一个整型值并赋值给x.a;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,447评论 1 51
  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,387评论 3 44
  • 轻轻合上整本书,抬起酸痛的脖子望向壁钟,已12点20分,我足足花了四个小时一口气把这本《故乡是潮汕》余下的180页...
    海言的时光阅读 237评论 0 0
  • 讲师训班长职责 将军的风度和果断: 带头完成各项任务和指标, 以最严格的标准...
    月光宝盒里的白晶晶阅读 93评论 0 0
  • 1 熙来人往的街让人彷徨,路边的音响兀自歌唱 是什么歌? 漫漫停下脚步,静静的听着,街边的喧闹被放到一边 她听得入...
    我要一所大房子阅读 163评论 0 0