C语言-结构体

目录

结构体的声明

结构体的初始化和声明

注意

.操作符和->操作符

句点操作符

->操作符

​编辑

计算结构体的大小

为什么存在结构体对齐

结构体传参

结论

结构体实现位段

位段的内存分配

总结


结构是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量,如: 标量、数组、指针,甚⾄是其他结构体。

结构体的声明

// 假如需要描述一个学生,那么需要char类型的名字;int类型的年龄等等

struct Stu

{
    char name[20];//名字

    int age;//年龄

    char sex[5];//性别

    char id[20];//学号

};//分号不能掉

结构体的初始化和声明

因为生成变量的时候需要进行初始化,所以我们不为结构体成员赋值。而是进行初始化。

#include <stdio.h>
#define NAME_LEN 64

struct student
{
    char name[NAME_LEN];
    int age;
    char sex[20];
    char id[20];
};

int main()
{
    struct student chen = { "Chen",20,"男","2021" };
    printf("姓名=%s\n", chen.name);
    printf("年龄=%d\n", chen.age);
    printf("性别=%s\n", chen.sex);
    printf("学号=%s\n", chen.id);
    return 0;
}

运行结果如下图所示:

注意

声明结构体时所赋的初始值的形式是逗号,将各个结构体成员的初始值依次排列在{ }里面,并使用逗号分割。未赋初始值的成员被初始化为0.

.操作符和->操作符

句点操作符

在上图所示代码当中,我门使用了.操作符来访问结构体对象。该操作符被称为句点操作符。

->操作符

计算结构体的大小

要计算结构体的大小,首先得掌握结构体内存对齐的规则。

  1. 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处
  2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。

对齐数 = 编译器默认的⼀个对齐数与该成员变量大小的较小值。(VS默认对齐数是8)

  1. 结构体总大小为最大对齐数(结构体中每个成员变量都有⼀个对齐数,所有对齐数中最大的)的整数倍。
  2. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到⾃⼰的成员中最大对齐数的整数倍处,结构 体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对⻬数)的整数倍。

示例如下图:

这两个结构体,里面的成员类型是一样的。但大小却不相同。原因如下图所示。

根据上面的规则充分的解释,这张图的来源。首先结构体的第一个成员需要对齐到偏移量为0的位置,所以S1和S2都是从零开始,然后根据第二条规则,对齐数需要为整数倍,那么int类型的大小是4,而默认值为8,所以需要S1要浪费掉3个字节,从4开始往下存储4个字节;而S2只需要接着往下存储一个空间即可。最后根据结构体结构体总大小为最大对齐数的整数倍,S1的最大对齐数是4,现在只占了9个字节所以还得浪费3个字节,所以总大小才是12;而S2则是正好8个字节。所以,在安排结构体成员的时候也需要调整位置。

为什么存在结构体对齐

  1. 平台问题:不是所有硬件平台都能访问任意地址上的任意数据。
  2. 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问,而对齐的内存仅需要一次。
  3. 总体来说:结构体的内存对齐是拿空间换取时间的做法。

结构体传参

在示例代码中,print2函数要更好一些。原因是,函数在传参的时候,参数需要压栈,会有时间和空间上的系统开销。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销较大,会导致性能的下降。

结论

结构体传参的时候,要传结构体的地址。

结构体实现位段

这个A就是一个位段类型。

位段的内存分配

  1. 位段的成员可以是int、unsigned int、signed int或者char等类型
  2. 位段的空间是按照需要以4个字节(int)或者1个字节(cahr)的方式来开辟的
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避使用位段。

总结

跟结构相比,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值