自定义类型(结构体、位段、枚举和联合)

时间:2020-12-24 16:08:32

 结构体常用于数据的大体模板相同,但具体的内容不同。例如:学生的信息都包括学号,姓名,年龄等信息,但是每个学生的信息的内容不同。这时就要用到结构体的创建。

1.定义结构体变量(以学生信息为例)

struct stu

{

      char name[20];

      int age;

}student;

也可以用struct stu student;来定义结构体变量。

当然也可以用

typedef struct stu

{

      char name[20];

      int age;

};

这时就创建了一个新的结构体变量stu,应用这种方法可以实现简便的结构体变量的定义。stu student;来定义结构体的变量。

在这里有几种常见的较难理解的结构体创建

(1)自引用

struct stu

{

    int date;

    struct stu* next;

}student;

这种类型简单来看就是构成了一个链表,访问student,访问到指针,在此跳转到student结构体的头,以此往复,构成链表。

(2)结构体的不完整声明

struct A

{

    int date;

    struct B* next;

};

struct B

{

    int date;

    struct A* next;

};

在声明结构体时,内存会给结构体创建内存空间,这时就会计算结构体的大小,而按照上述的创建,A的结构体因为包含有B的结构体类型的指针,所以在计算A的大小时,就要访问B,计算B的大小,但是B又要计算A的大小,这就相当于无限次的递归,却没有递归出口。所以就会显示错误。所以在创建时,可以在A之前对结构体B进行声明。

2.结构体的初始化

可以整体进行赋值语句,例如struct stu student ={"zhangsan",20};

而在上述创建中提到的含有指针的结构体的初始化可以使用结构体嵌套初始化,例如struct A p={20,{4,5},NULL};

3.结构体内存对齐

   这里给大家讲一个较为典型的例子。(以visual stdio 2013为例,默认的对齐数为8)

struct s1

{

     char c1;       //大小为1,在这里特别注意第一个字节也有对齐数,但是不需要对齐,所以这里要加上7//大小8

     struct s3 s;     //这里s3的大小为16     //已对齐,大小8+16=24;

     char c2;       // 大小24+1=25;

     struct s3 s[2];   //没有对齐,加上7,结构体的大小为32,大小变为25+7+32=64;

     struct s3 *p;     //这里以对齐,指针大小为4,所以大小64+4=68;

     double d;        //这里没有对齐,加上4,double的大小为8,大小为68+4+8=80;这时为8的整数倍,既可以。大小为

}                           //80

4.位段

struct A

{

    int   _a:2;

    int   _b:5;

    int   _c:10;

    int   _d:30;

};

形如以上类型的便是位段,位段是针对于比特位而言的,冒号之后的就是相应要使用的比特位,以上例为例:求其大小:第一个int 类型有32位比特位,a使用2个比特位,b使用5个比特位,c使用10个比特位,这时第一个int型还剩下15个比特位,而d需要30个比特位,明显比特位不够,所以要再开辟一个int大小的32位比特位,再这里要特别注意,当比特位不够时,新的比特位要从新的int 来开始,这是和内存的存储数据的方式有关。所以该位段的大小为2.

5.枚举

enum color

{

    red=1;

    green=2;

    blue=4;

};

使用枚举类型时,将enum color clr=green;在这里枚举就相当于一个新的color类型,对其进行赋值,在这里需要注意的是如果没有对齐枚举中的内容赋值时,输出的值就为前一个的值加1,所以此时若输出枚举内容相应的取值,输出red=1,green=2;blue=3; 

   6.联合

union un

{

   char c[5];        //这里的大小为5

   int i                //大小为4               //选择最大的为5,发现不是8的整数倍,所以大小为8

}

union un u;

在这里需要注意的是,可以将联合体看做一个变量,但是只能访问一个值,也就相当于访问首地址。

所以,如果你打印i和c的地址的话,会发现两者的地址相同。

特别注意联合体的对齐方式,以上边的例子为例,看注释。

     以上就是一些自定义的相关内容,在这里要注意所有的自定义都需要考虑内存对齐的问题,但是尤其结构体更需要考虑,在此,就简单的为大家做了一些介绍,希望对大家以后的学习有所帮助!