zoukankan      html  css  js  c++  java
  • 结构体struct、联合体union、枚举类型enum

    1.c语言中的类型

    1)内置类型——char,short,int,float,double;

    2)用户自定义类型(UDT)——struct结构体,union联合体,enum枚举类型

    2.内存对齐

    2.1概念

    1)内存对齐就是编译器为程序中的每个“数据单元”安排在适当的位置上

    2)对于内存对齐问题,主要存在于struct和union等复合结构在内存中的分布情况

    2.2规则

    1)对于结构的各个成员,第一个成员位于偏移为0的位置,以后的每个数据成员的偏移量 = min ( #pragma pack(n) 指定的n值, 这个数据成员的字节数 ) 的倍数,#pragma pack(n)可以设置, Windows中默认为8,Linux中默认为4;

    2)结构或联合体本身也要进行对齐,其字节大小=min( #pragram pack(n) ,  长度最长的数据成员 )的倍数

    struct MyStruct    //MyStruct的内存分布:*xxx | **** | **        (*代表使用,x代表未使用)
    {
        char a;    //偏移量为0
        int b; //偏移量为4
        short c; //偏移量为8
    };
    //windows下MyStruct的字节大小为:1+4+2=7,变成4的倍数:12

    2.3为什么要内存对齐

    1)平台原因:不是所有的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常

    2)性能提升:经过内存对齐之后,CPU的内存访问速度大大提升,原因:

    • 内存读取粒度:cpu把内存当成是一块一块的,块的大小可以是2,4,8,16 个字节,因此CPU在读取内存的时候是一块一块进行读取的,块的大小称为(memory granularity)内存读取粒度
    • 假设CPU要读取一个4字节大小的数据到寄存器中(假设此CPU内存读取粒度是4),分两种情况讨论:
    1.  数据从0字节开始:直接将0~3四个字节完全读取到寄存器,完成,这时候没有任何影响
    2.  数据从1字节开始:首先先将0~3的4个字节读到寄存器,并再次读取4~7字节的数据进寄存器,接着把0、5、6、7的数据剔除,最后合并1,2,3,4字节的数据进寄存器,这些额外操作大大降低了CPU的性能

    2.union联合体

    2.1概念

    1)联合体union类似于结构体struct(struct概念:不同类型数据的集合体)

    2)联合体用同一段内存单元存放不同数据类型的成员,在使用时,一次只能使用其中的一个成员

    3)它的所有成员相对于基地址的偏移量都为0

    4)union的大小取决于它所有的成员中,占用空间最大的一个成员的大小,并且union的大小要能被其他成员的大小所整除

    union U1
    {
        char s[11];
    };
    
    union U2    //s占11字节,n占4字节,d占8字节,所以至少需11字节的空间,但11不能被8整除,所以补充字节到16
    {
        int n;
        char s[11];
        double d;
    };
    
    int main()
    {
        cout << sizeof(U1) << endl;        //输出:11
        cout << sizeof(U2) << endl;        //输出:16
    
        return 0;
    }

    2.2应用

    1)当多个类型的变量要占用同一片内存时,可以使用联合体:检测当前机器是采用大端还是小端

    2)当多个事物只取其一时(“n选1”),可以使用联合体:

    试题:假设网络节点A和网络节点B中的通信协议涉及四类报文,报文格式为“报文类型字段+报文内容的结构体”,四个报文内容的结构体类型分别为Struct1~ Struct4,请编写程序以最简单的方式组织一个统一的报文数据结构。
    分析:
    报文的格式为“报文类型+报文内容的结构体”,在真实的通信中,每次只能发四类报文中的一种,我们可以将四类报文的结构体组织为一个union(共享一段内存,但每次有效的只是一种),然后和报文类型字段统一组织成一个报文数据结构。
    //报文内容联合体
    union PacketContent
    {
        Struct1 pkt1;
        Struct2 pkt2;
        Struct3 pkt1;
        Struct4 pkt2;
    };
    
    //统一的报文结构
    struct Packet
    {
        unsigned char pktType;//报文类型
        PacketContent pktContent;//报文内容
    };

    4.enum枚举类型

    4.1概念

    1)枚举可以让一些数字符号化

    2)c语言中枚举常量是按照int来处理

    3)c语言的枚举变量可以++,c++的枚举变量不可以

    4.2定义的格式

    enum 枚举类型名 {枚举常量0=int常量(可无,默认值为0),枚举常量1=int常量(可无,默认值为1),枚举常量2,枚举常量3=int常量(可无,默认值为3),…};
    enum Color { red, blue };
    enum Color cfq;
    cfq = red;
    ++cfq;    //c语言的枚举变量可以++
    enum Color { red, orange, blue };
    Color hehe;
    hehe = red;
    ++hehe;    //错误,c++的枚举变量不可以++
  • 相关阅读:
    高性能javascript 笔记 第一章 loading and executing (一)
    css 微信webui
    C语言之指针
    Java中的异常
    Java中的接口
    SQL Server中自连接和联合的用法
    SQL Server中多对多关系的实现
    SQL Server中用SQL命令建表和主外键约束
    SQL Server中的分页查询
    SQL Server中的内连接
  • 原文地址:https://www.cnblogs.com/Joezzz/p/10273085.html
Copyright © 2011-2022 走看看