美文网首页
数据结构 -- 结构体Struct

数据结构 -- 结构体Struct

作者: 东篱采桑人 | 来源:发表于2020-09-16 19:10 被阅读0次

C语言中,可以使用结构体(Struct)来存放一组不同类型的数据。结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称为结构体的成员(Member)。结构体的定义形式为:

struct 结构体名{
    结构体所包含的变量或数组
};

1. 定义结构体变量

结构体是一种自定义的数据类型,是创建变量的模板,不占用内存空间。结构体变量才包含了实实在在的数据,需要内存空间来存储。

  • 方式一:先定义结构体,再定义结构体变量
//定义stu结构体
struct stu{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在学习小组
    float score;  //成绩
};

//定义两个结构体变量
struct stu stu1, stu2;

stu为结构体名,里面包含name、num、age、group、score这5个成员。stu1stu2则为两个stu类型的结构体变量。

  • 方式二:在定义结构体的同时定义结构体变量
struct stu{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在学习小组
    float score;  //成绩
} stu1 stu2;

直接将变量放在结构体的最后即可。

如果只需要 stu1、stu2 两个变量,后面不需要再使用结构体名定义其他变量,那么在定义时也可以不给出结构体名。

  • 注意:在结构体内部定义结构体
struct stu{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    struct sub1{
        char group;  //所在学习小组
    } sub1;
    struct sub2{
        float score;  //成绩
    };
};

如上所示,在stu结构体里还定义了『结构体变量sub1』和『结构体sub2』,由于sub2没有定义变量,所以其内部成员score即为母结构体stu的成员变量。

2. 成员的获取和赋值

使用点号.获取结构体变量的单个成员,然后再进行赋值操作。

//给结构体成员赋值
stu1.name = "Tom";
stu1.num = 12;
stu1.age = 18;
stu1.group = 'A';
stu1.score = 135;

//读取结构体成员的值
printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", stu1.name, stu1.num, stu1.age, stu1.group, stu1.score);

//打印结果
Tom的学号是12,年龄是18,在A组,今年的成绩是135!

也可以在定义结构体变量时整体赋值:

struct{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在小组
    float score;  //成绩
} stu1, stu2 = { "Tom", 12, 18, 'A', 136.5 };

3. 结构体的内存分配

结构体中各成员在内存中是按顺序依次存储的,成员之间不互相影响,各占用不同的内存空间。结构体变量占用的内存大于等于所有成员占用的内存的总和,因为成员在存储时需要遵循结构体的内存对齐规则,成员之间可能会存在裂缝。

结构体内存对齐

4. 计算结构体的内存大小

先来看看结构体的内存对齐规则:

1. 数据成员对⻬规则:结构体的第⼀个数据成员会存放在offset为0的地⽅,以后每个数据成员存储的起始位置要从该成员⼤⼩或者成员的⼦成员⼤⼩(只要该成员有⼦成员,⽐如说是数组, 结构体等)的整数倍开始存储(⽐如int为4字节,则要从4的整数倍地址开始存储)。

2. 结构体作为成员:如果⼀个结构里有某些结构体成员,则结构体成员要从其内部最⼤元素所占内存⼤⼩的整数倍地址开始存储。(struct a⾥存有struct b,b⾥有char, int, double等元素,那b应该从8的整数倍开始存储.)

3. 总内存对齐:结构体的总⼤⼩,也就是sizeof的结果,必须是其内部最⼤成员所占内存大小的整数倍,不⾜的要补⻬。若结构体a里包含结构体成员b,则需要将a的其他成员和b里的成员相比,得到最大成员内存,再按照最大内存的倍数进行补齐。

看完内存对齐规则是不是感觉有点绕?不急,接下来通过分析具体例子来理解这个规则。

示例1:含有多种数据类型成员

struct Struct {
    double a;   //8 (0-7)
    char b;     //1 [8 1] (8)
    int c;      //4 [9 4] 9 10 11 (12 13 14 15)
    short d;    //2 [16 2] (16 17)
} struct1;

//输出内存大小
printf("struct1 = %lu \n", sizeof(struct1));

//输出结果
struct1 = 24    

输出结果分析:

  • double a:a占用8字节内存,作为第一个成员,a会在结构体所在内存中的0-7的位置存放。
  • char b:b只占用1个字节内存,会按顺序存放在位置8处。
  • int c:c占用4字节内存,本该从位置9开始存放,但根据规则1可知,c必须从4的整数倍开始存储,而9不是4的整数倍,需要后移到位置12才开始存储,所以c存放在结构体内存中的12-15的位置。
  • short d:d占用2字节内存,可以接着从位置16开始存储,所以存放在16-17的位置。

根据上面的分析可知,struct1的成员总共需要18字节内存,根据规则3,struct1的内存大小必须是8(double a)的整数倍,所以最后内存大小为24。

sizeof:是一个运算符,用来计算传进来的数据类型占用多大的内存,在编译时即可完成运算。比如:sizeof(int)为4字节,sizeof(double)为8字节。

示例2:交换成员位置

struct Struct {
    double a;   //8 (0-7)
    int c;      //4 (8 9 10 11)
    char b;     //1 (12)
    short d;    //2 [13 2] (14 15) - 16
} struct2;

//输出内存大小
printf("struct2 = %lu \n", sizeof(struct2));

//输出结果
struct2 = 24    

这次在示例1中struct的基础上交换了成员b和c的位置,输出结果就不一样了,分析如下:

  • double a:a占用8字节内存,作为第一个成员,a会在结构体所在内存中的0-7的位置存放。
  • int c:c占用4字节内存,可以接着从位置8开始存储,所以c存放在结构体内存中的8-11的位置。
  • char b:b只占用1个字节内存,可以直接存放在位置12处。
  • short d:d占用2字节内存,本该从位置13开始存放,根据规则1可知,由于13不是2的倍数,需要后移到位置14开始存储,所以存放在14-15的位置。

根据上面的分析可知,struct2的成员总共需要16字节内存,根据规则3,struct2的内存大小必须是8(double a)的整数倍,所以最后内存大小为16。

示例3:结构体嵌套结构体

直接在struct1里加上一个struct2成员,然后输出内存大小

//在最后加上成员e
struct Struct1 {
    double a;   // 8
    char b;     // 1
    int c;      // 4
    short d;    // 2
    struct Struct2 e;  //16
} struct1;

//输出内存大小
printf("struct1 = %lu \n", sizeof(struct1));

//输出结果
struct1 = 40

从之前struct1的分析可知,a、b、c、d实际占用18字节(位置0-17),那成员e就需要从位置18开始存放。由于e是个结构体,根据规则2,当结构体作为成员时,需要从其内部最⼤元素所占内存⼤⼩的整数倍地址开始存储。结构体e中内存占用最大的元素是double a,为8字节,所以e就需要从8的整数倍地址开始存储,即后移到位置24开始存储,e本身占用16字节内存,所以存放位置是24-39。

根据上面的分析可知,struct1的成员总共需要40字节内存,根据规则3,struct1的内存大小必须是8(double a)的整数倍,所以最后内存大小为40。

对于这个示例,大家可以改变成员e在Struct1中的位置,或者更改struct1和e里的成员类型,再看下输出结果和自己计算的结果是否相同。

推荐阅读

1. 数据结构 -- 共用体Union
2. 数据结构 -- 位域

相关文章

  • 第十一章-结构体与共用体(知识点)

    一、结构体知识点: 1、用户自己指定一种数据结构,它称为结构体(structure)。 2、struct 结构体名...

  • 数据结构 -- 结构体Struct

    在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据。结构体是一种集合,它里面包含了多个变量或数组,...

  • 玩转redis缓存

    五种数据结构简介 Redis是使用C编写的,内部实现了一个struct结构体redisObject对象,通过结构体...

  • 菜鸡学Swift3.0 13.结构体

    结构体 struct 是值类型 1.定义结构体 struct 结构体类型 { var 结构体属性:类型 ...} ...

  • 数据结构 -- 共用体Union

    在数据结构 -- 结构体Struct一文中详细介绍了结构体的定义以及内存对齐。在C语言中,还有另外一种和结构体非常...

  • 【OC梳理】结构体、枚举

    结构体(struct) OC中的结构体(struct),其实就是C语言中的结构体(struct)常见使用方法。OC...

  • 嵌入式学习笔记19.11.25

    c语言结构体 结构体一般定义全局变量 struct stu{//struct 定义结构体 stu 结构体名称 in...

  • 单链表:一种最简单的动态数据结构。单链表结构体中包含有指向下一结构体的指针。形式如下:struct linkl...

  • C语言基础6

    结构体概述 1 在C语言中,结构体(struct)指的是一种数据结构,是C语 言中构造类型的其中之一。 2 在实际...

  • C语言中__packed 和位段的理解

    一:__packed typedef __packed struct struct常用在数据结构中。而struct...

网友评论

      本文标题:数据结构 -- 结构体Struct

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