【C语言】结构体类型和结构体变量(字节对齐)

目录

一、结构体类型定义

二、结构体变量的定义

①先定义结构体类型,再定义结构体变量

②在定义结构体类型的同时,定义结构体变量

③直接定义结构体变量

三、结构体变量的内存分配

四、结构体变量的初始化

五、结构体变量的引用


一、结构体类型定义

结构体是一种构造数据类型,可以把不同类型的数据整合在一起,每一个数据都称为该结构体类型的成员。使用结构体时,首先需要对结构体类型进行定义,结构体类型的定义如下所示:

struct 结构体类型名称

{

    数据类型   成员名1;

    数据类型   成员名2;

  。。。

};

//"struct"是定义结构体类型的关键字

实例演示:

学生信息包括:学号(num)、姓名(name)、性别(sex)、年龄(age)、地址(address),将其定义为一个名为Student的结构体。

struct Student
{
    int num[10];
    char name[10];
    char sex;
    int age;
    char address[30];
};

【注意】结构体类型中的成员,也可以是一个结构体变量。

实例分析:

struct Date
{
    int year;
    int month;
    int day;
};

struct Student
{
    int num[10];
    char name[10];
    char sex;
    struct Date birthday;//出生日期birthday为结构体类型Date
}stu1;

此时结构体类型Student的类型结构如下:

【注释】

  • 结构体类型定义以“struct”开头,后面跟的是结构体类型的名称,该名称的命名规则与变量一致
  • 定义好一个结构体类型后,并不意味着立即分配一块内存单元存放各个数据成员,它只是告诉编译器,该结构体类型由哪些数据类型的成员构成,各占多少个字节,按什么格式存储,并把它们当作一个整体来处理。
  • 结构体类型定义的末尾括号的分号必不可少
  • 结构体类型的成员可以是一个变量,但不能是自身结构体类型的变量。

二、结构体变量的定义

定义了结构体类型,系统不会为它分配内存空间。为了能在程序中使用结构体类型的数据,应该定义结构体类型的变量,并在其中存放具体的数据。定义结构体变量的方法主要有下面三种:

①先定义结构体类型,再定义结构体变量

struct Student
{
    int num[10];
    char name[10];
    char sex;
    int age;
    char address[30];
};

struct Student stu1,stu2;
//stu1、stu2为结构体类型变量,各自可以存储一组基本类型的变量,且分别占据一块连续的内存空间

②在定义结构体类型的同时,定义结构体变量

struct Student
{
    int num[10];
    char name[10];
    char sex;
    int age;
    char address[30];
}stu1,stu2;
//变量stu1和stu2的数据类型都是结构体类型Student

③直接定义结构体变量

struct 
{
    int num[10];
    char name[10];
    char sex;
    int age;
    char address[30];
}stu1,stu2;
//stu1、stu2为结构体变量,但定义的结构体没有类型名称(又称“匿名结构体”)

【注意】结构体类型是用户自定义的一种数据结构,它同简单数据类型一样,在编译时对结构体类型不分配空间。只有在用它定义某个变量时,才会为该结构体变量分配结构体类型所需大小的内存单元。


三、结构体变量的内存分配

结构体变量一旦定义,系统就会为它分配内存空间。结构体变量占据的内存大小是按字节对齐机制来分配的。

字节对齐:字节按照一定规则在空间上排列。字节对齐遵循两条规则:

结构体的每个成员变量相对于结构体首地址的偏移量,是该成员变量的基本数据类型(不包括结构体、数组等)大小的整数倍;如果不够,编译器会在成员之间加上填充字节。

实例分析:

struct
{
    char a;
    double b;
    int c;
    short d;
}S;

结构体变量S中各个成员在内存中分布情况如下:

为什么有7个字节的填充字节?

成员变量a的地址为结构体变量S的首地址,占1字节;成员变量b占8个字节,但是如果字节跟着变量a后面,就违背了字节对齐原则①,所以至少需要在前面填充7个字节,使得变量的地址相对于首地址是整数倍。变量c,d相对于首地址的偏移量分别是16,20字节正好是4和2的倍数。

结构体的总大小为结构体最长的结构体成员变量大小的整数倍,如果不够,编译器会在最末尾一个成员之后加上填充字节

根据原则①计算出上述的结构体变量S所占的内存大小为22字节,但这个不符合字节对齐的原则②,不是8的倍数,因此编译器会在最后填充两个字节,使之成为24字节。

#include <stdio.h>

struct
{
    char a;
    double b;
    int c;
    short d;
}S;

int main() {
    printf("结构体变量S占字节大小为:%d\n", sizeof(S));
}

运行结果:


四、结构体变量的初始化

结构体变量中存储的是一组类型不同的数据,因此,为结构体变量初始化的过程,实际就是为结构体个成员初始化的过程。

结构体变量初始化的方式有下面两种:

①在定义结构体类型和结构体变量的同时,对结构体变量进行初始化

struct Student
{
    int num;
    char name[10];
    char sex;
    int age;
}stu={1001,"Li Lei",'M',18};
//结构体变量stu定义的同时进行了初始化

②先定义结构体类型,再在定义结构体变量的同时进行初始化

struct Student
{
    int num;
    char name[10];
    char sex;
    int age;

};

struct Student stu={1001,"Li Lei",'M',18};

【注意】在对结构体初始化时,如果只初始化其中一部分成员,只需要对前面的成员初始化,后面的成员可以空余,因为给成员变量赋值时,编译器是按成员从前往后匹配,而不是按数据类型自动匹配


五、结构体变量的引用

定义并初始化结构变量的目的是使用结构体变量的成员。结构体变量的引用方式如下:

结构体变量名.成员名

#include <stdio.h>

struct Student
{
    int num;
    char name[10];
    char sex;
    int age;
  
};

struct Student stu = { 1001,"Li Lei",'M',18 };

int main() {
    printf("学生信息:\n");
    printf("学号:%d\n", stu.num);
    printf("姓名:%s\n", stu.name);
    printf("性别:%c\n", stu.sex);
    printf("年龄:%d\n", stu.age);
}

运行结果:

 

  • 10
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值