• 结构体【重要】


    继续进行C语言学习之旅,现在已经快进入了C的核心了,所以需更加细心地学习,言归正传,开始学习:

    什么是结构体呢?

    定义结构体类型:
     
    注意:结构体最后的分号不能省略
    这时编译就出错了:
     
    结构体变量:
    当我们定义好了一个结构体类型之后,就可以使用它,类似于基本类型一样,但是:会有一些差别
    ①使用方式一【用得较少】:
     
    注意:struct关键字不能省略,代表该变量是一种结构体类型:
     
    这时编译就出错了:
    ②使用方式二【用得较少】:
     我们可以将结构体声明在函数体内,声明之时就给出变量:
    ③使用方式三【通常用这种方式】:
    使用方式一中可以看出,使用起来不是那么方便,有没有解决办法呢?答案当然有,也就是第三种方式,用typedef为现有类型创建一个新的名字,或称为类型别名
     
     
    另外,我们可以简化这种方式,在定义结构体类型之后,就给出别名,还不用单独多出一行来处理【在编程中能用少的代码来实现同样的功能,是我一直追求的!!】
     
    编译也是成功的:
     
    提示:对于用tydef给一个类型定义别名,一般命名是以_t结尾:
     
     
    结构体中可以嵌套结构体:
    #include <stdio.h>
    
    struct point
    {
        int x;
        int y;
    };
    
    typedef struct point point_t;
    
    typedef struct circle
    {
        point_t center;//嵌套结构体
        int radius;
    } circle_t;
    
    int main(void)
    {    
        return 0;
    }
     
    结构体变量初始化:
    ①第一种初始化:
    #include <stdio.h>
    
    struct point
    {
        int x;
        int y;
    };
    
    typedef struct point point_t;
    
    typedef struct circle
    {
        point_t center;
        int radius;
    } circle_t;
    
    int main(void)
    {
    
        circle_t c1 = {{1, 2}, 3};
    
        printf("(%d,%d) %d\n", c1.center.x, c1.center.y, c1.radius);
    
        return 0;
    }

    说明:访问结构体里面的元素,采用“.”:

    ②第二种初始化:
     
    #include <stdio.h>
    
    struct point
    {
        int x;
        int y;
    };
    
    typedef struct point point_t;
    
    typedef struct circle
    {
        point_t center;
        int radius;
    } circle_t;
    
    int main(void)
    {
    
        circle_t c1 = {1, 2, 3};
    
        printf("(%d,%d) %d\n", c1.center.x, c1.center.y, c1.radius);
    
        return 0;
    }

    ③第三种初始化:
     
    #include <stdio.h>
    
    struct point
    {
        int x;
        int y;
    };
    
    typedef struct point point_t;
    
    typedef struct circle
    {
        point_t center;
        int radius;
    } circle_t;
    
    int main(void)
    {
    
        point_t p1 = {1, 2};
        circle_t c1 = {p1, 3};
    
        printf("(%d,%d) %d\n", c1.center.x, c1.center.y, c1.radius);
    
        return 0;
    }

    我们知道数组是不能整体赋值的,这个在http://www.cnblogs.com/webor2006/p/3452229.html有说明,下面再回忆一下:
     
     
    要真的想把一个数组的值赋给另外一个数组,只能采用遍历的方式:
     
     
     而对于字符数组,也是无法直接整体赋值的:
    编译,这时会出错:
    如果要从一个字符数组的内容拷贝到另外一个数组,则需要利用库函数来实现:
    编译,运行:
    但是结构体中的数组是可以相互赋值的:
    #include <stdio.h>
    
    typedef struct test
    {
        int a[3];
        int b;
        char c[10];
    } test_t;
    
    
    int main(void)
    {
    
        test_t t = {{4, 5, 6}, 100, "hello"};
        test_t t2;
        t2 = t;//结构体整体赋值
    
        printf("%d %d %d %d %s\n", t2.a[0], t2.a[1], t2.a[2], t2.b, t2.c);
    
        return 0;
    }

     
    结构体数组:
    由于结构体也是一种数据类型,所以很容易地可以想到它可以有数组:
     
    结构体内存对齐【这个概念重要】:
     看如下图:
     
     
     
    从结果来看,并非按我们推算的来计算结构体的大小,这是因为结构体里面的数据是按对齐的方式来存放的,把数据地址对齐到2、4、8(这里称为对齐模数,不同数据类型的对齐模数是不一样的)的整个倍,这就是所谓的“结构体内存对齐”
    可能有些抽象,至于怎么对齐,下面会详细介绍,这阶段先初步解释上程序中16的字节数是怎么得来的
     
     
     下面通过一个图来说明意义:
    先讨论对齐的方式存放:
     
    而如果不以对齐的方式存放呢?
    可见,这种方式的效率远不如对齐的,所以对齐的重要意义为:
     
    这是关键点,先说下规则:
    ①:第一个数据成员对齐至偏移值为0的地方。
    ②:接下来的数据成员对齐至对齐模数的整数倍,每个数据成员都有自己的对齐模数。
    ③:对齐模数取数据成员的大小与param pack(n)(对齐值,gcc默认为4,微软的vc默认是8)的较小值。
     
    ④:整个结构体的大小对齐至最大对齐模数的整数倍。
     
     
    下面通过设置param pack(n)来看下,结构体的大小是否发生了变化:
    运行结果:
    这时,我们来算一下,这个值是怎么得来的:
     
    如果我们将对齐值改为1呢?
    运行结果:
    通过上面的分析就可以很清楚地推出为啥输出是10个字节的大小了
    如果将对齐值改为8呢?
    运行结果:
     
    这是为什么呢?原因是因为gcc中的对齐值只能是1、2、4,不支持8,只有在vc上才会支持
     
    结构体位字段:
     
     
     
     
     
     
    联合体:
    “联合”与“结构”有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间,一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间,一个联合变量的长度等于各成员中最长的长度。【来自于百度百科】
     
     
     
    下面用一个实例来体会一下联合体:验证一下机器是小端字节序还是大端字节序
    先介绍一下什么是“小端字节序”和“大端字节序
    接着用联合体来编程验证:
     
     
    好了,结构体这一章是非常重要的,涉及到的细节也是挺多的,需好好消化。
  • 相关阅读:
    信息安全系统设计基础第二周学习总结(20135213)
    《深入理解计算机系统》第一节课课堂笔记(20135213)
    (20135213)信息安全系统设计基础第一周学习总结(共12课)课程(6~12)
    (20135213)信息安全系统设计基础第一周学习总结(共12课)课程(1~5)
    实验五 — — Java网络编程及安全
    20135220谈愈敏--信息安全系统设计基础期中总结
    20135220谈愈敏-第三章家庭作业
    20135220谈愈敏--信息安全系统设计基础第六周学习总结
    20135220谈愈敏-第二章家庭作业
    20135220谈愈敏--信息安全系统设计基础第五周学习总结
  • 原文地址:https://www.cnblogs.com/webor2006/p/3462258.html
Copyright © 2020-2023  润新知