美文网首页程序员@IT·互联网
详解C语言结构和联合

详解C语言结构和联合

作者: d9fc24a0c9a9 | 来源:发表于2017-09-24 17:53 被阅读188次

    结构体基础

    聚合类型——能够同时存储超过一个单独的数据,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;

    相关文章

      网友评论

        本文标题:详解C语言结构和联合

        本文链接:https://www.haomeiwen.com/subject/tmckextx.html