• C语言结构体


    C语言结构体初始化的四种方法

    C语言聚合数据类型包括数组和结构体,其中数组中是相同类型的元素的集合,可以通过下标引用或之子很间接访问,但结构体各个成员可以是不同的数据类型。

    结构声明

     完整的结构声明:struct tag {number-list} variable-list; 黑体部分至少要出现两个。

    {number-list}和variable-list,每次声明新变量都要用单独的声明,而且每次声明后并不是同一种类型,尽管结构体内容完全一样

     1 struct {
     2     int a;
     3     float b;
     4     char c;
     5 }x;
     6 
     7 struct {
     8     int a;
     9     float b;
    10     double c;
    11 }*z;
    12 
    13 z = &x;//这样赋值是错误的,因为类型不一致,但C语言会忽略,C++会报错

      tag和{number-list},这样不用每次都使用单独的声明,只用struct tag即可对结构变量进行声明。

    1 struct temp{
    2     int a;
    3     float b;
    4     char c;
    5 };
    6 struct temp x;
    7 struct temp *z;

     typedef、{number-list}和name,这样不用每次都使用单独的声明,只用name即可对结构变量进行声明,比上面的tag更加简洁,这时name是类型名,而不是结构标签。

    1 typedef struct {
    2     int a;
    3     float b;
    4     double c;
    5 }temp;
    6 temp x;
    7 temp *z;

     结构体初始化

    (1)定义时赋值,需要对应顺序,不能错位

     1 temp x = {1, 2.3, 4.66}; 

    (2)定义后逐个赋值

    temp x;
    x.a = 1;
    x.b = 2.3;
    x.c = 4.66;
    

    (3)定义时乱序赋值(C风格),这种方法在Linux内核(kernel)中经常使用,在音视频编解码库FFmpeg中也大量频繁使用,还是很不错的一种方式。

    temp x = {
    	.b = 2.3,
    	.a = 1,
    	.c = 4.66
    
    };
    

    (4)定义时乱序赋值(C++风格),类似于key-value键值对的方式

    temp x = {
    	b : 2.3,
    	a : 1,
    	c : 4.66
    };

    访问结构成员

    (1)直接访问

     如上面声明的结构体变量所示,对x中的成员进行访问时,如下访问

    int m = x.a; 
    float = x.b;

    (2)间接访问

     如果存在指向结构体的指针,则如下访问

    int m = (*z).a;
    int m = z->a;

    结构的自引用

     结构内部包含一个类型为结构本身的成员,为自引用,高级的数据结构,链表和树都用到了该种结构。

    声明时,编译器需知道结构体的大小,以便分配内存空间,所以不能直接用该结构体,否则会无限循环下去,无法知道结构体的大小。因此需要对该结构体成员使用指针。指针长度是固定的,取决于使用的机器和编译器,因此长度可知。

     1 typedef struct {
     2     int a;
     3     temp *b;
     4     double c;
     5 }temp; 
     6 //上面是错误的
     7 typedef struct selftemp_tag{
     8     int a;
     9     struct selftemp_tag *b;
    10     double c;
    11 }selftemp;

    上面的声明是错误的,因为temp *b在声明之前就使用了。下面的声明中,定义了一个tag标签来解决该问题,同时标签前需加struct。

    结构的互引用(不完整声明,还不知道怎么用)

     结构体之前互相引用,那么哪个结构应该首先声明呢?问题的解决方案是使用不完整声明,它声明一个作为结构标签的标识符

     1 struct B;
     2 
     3 struct A{
     4     struct B * partner;
     5     //其他声明
     6 };
     7 
     8 struct B{
     9     struct A * partner;
    10     //其他声明
    11 };

    在A的成员列表中需要标签B的不完整声明,一旦A声明之后,B的成员列表也可被声明.(并不知道怎么用)

    结构进行函数传参 

     结构变量用作函数参数进行传递时,如果传递整个结构体的话,结构体成员少时并没有影响,若成员很多,传递整个结构体会浪费内存空间,因此这时应该传递结构体指针,从而提高传递效率。

    联合

     如果想在不同时刻把不同的东西存储在同一个位置,就需要用到联合,声明和结构体类似

    union {
    	float f;
    	int i;
    }fi;

    当存储在同一位置的不仅仅是简单的整型或浮点型数值,而是完整的结构时,称为变体记录,具体程序实例参考《c和指针》P213

    联合的各个成员具有不同的长度,联合的长度就是它最长成员的长度,因此如果没有动态内存分配的话,默认按照最长成员的长度进行内存分配,会造成内存空间的浪费。

    联合的变量可以被初始化,但初始值必须是联合第一个成员的类型

    union {
    	float f;
    	int i;
    }fi = {0.5};

    初始化的值必须位于一对花括号里面。

  • 相关阅读:
    Unity 检查文件命名是否规范
    比特 bit 字节 byte ASCII码 Unicode UTF 32 UTF 8 傻傻分不清楚
    LuaJIT诡异bug(疑似)
    [转]现代密码学实践指南
    [转]安卓系统下luajit性能问题
    [转]用好lua+unity,让性能飞起来——luajit集成篇/平台相关篇
    lua string.format的bug(已知存在于lua5.1.5、LuaJIT-2.0.4)
    编译libmysqlclient.a静态库
    linux模拟复杂网络环境下的传输
    mingw & vs 兼容
  • 原文地址:https://www.cnblogs.com/qinguoyi/p/10130435.html
Copyright © 2020-2023  润新知