结构体与共用体

结构体类型就是一种自定义类型

  • 结构体使用时先定义结构体类型,然后再用类型来定义变量也可以在定义类型的同时定义变量
数组——>结构体
  1. 结构体可以认为是从数组发展而来的。其实数组和结构体都算是数据结构的范畴了,数组就是简单的数据结构、结构体比数组更复杂一些,链表、哈希表之类的比结构体又复杂了一些;二叉树、图等又更复杂一些。
  2. 数组有两个明显的缺陷:第一个是定义时必须给出明确的大小,且不能再更改;第二个时数组要求所有元素的类型必须一致。更复杂的数据结构就致力于解决数组的这两个缺陷。
  3. 结构体就是解决数组的第二个缺陷。
结构体变量中元素如何访问
  1. 用.或->的方式来访问(实质是一样的,只是C语言规定用结构体变量来访问元素用. 用结构体变量的指针来访问元素用-> 实际上在高级语言中已经不区分了,都用.)
  2. 结构体的访问方式有点类似于数组下标的方式
  3. 结构体的访问方式本质上还是指针方式访问
结构体的实质
  1. 结构体中元素的访问其实本质上还是用指针方式,结合这个元素在整个结构体中的偏移量和这个元素的类型来访问的。
  2. 但是实际上结构体的元素的偏移量更复杂,因为结构体要考虑元素的对齐访问,所以每个元素实际占的字节数和自己本身所占的字节数不一定完全一样。
  3. 一般来说,我们用.的方式来访问结构体元素时,我们是不用考虑结构体的元素对齐的。因为编译器会帮我们处理这个细节,但是因为C语言本身是很底层的语言,而且做嵌入式开发经常需要从内存角度,以指针方式来处理结构体及其中的元素,因此还是需要掌握结构体对齐规则。
结构体为什么要对齐
  1. 为了配合硬件,硬件上有物理上的限制。如果对齐排布和访问会提高效率,否则会大大降低效率
  2. 内存本身是一个物理器件(DDR内存芯片,SoC上的控制器),本身具有一定局限性:如果内存每次访问时按照4字节对齐访问,那么效率是最高的;如果不对齐访问效率低很多。
  3. 还有很多别的因素和原因,导致我们需要对齐访问。譬如Cache的一些缓冲特性,还有其他硬件的一些内存依赖特性,所以会要求内存对齐访问。
  4. 对齐访问牺牲了内存, 获得了速度 。非对其访问节省了内存,降低了速度。
  • 编译器本身可以设置内存对齐的规则,有以下的规则要记住:

    1. 32位的编译器,一般采用4字节对齐。
    2. 64位的编译器,一般采用8字节对齐。(win10都是64位)
  • 总结:结构体对齐的分析要点和关键

    1. 结构体对齐要考虑:结构体整体必须安置在四字节对齐处,结构体对齐后的大小必须时4的倍数(编译器设置为4字节对齐时,如果编译器设置为8字节对齐,则这里的4是8)
    2. 结构体中每个元素本身都必须对齐存放,而每个元素本身都有自己的对齐规则。
    3. 整个结构体变量4字节对齐是由编译器保证的,我们不用操心。然后是第一个元素a,a的开始地址就是整个结构体的开始地址,所以自然是4字节对齐的,但是a的结束地址要由下一个元素说了算。然后是第二个元素b,因为上一个元素a本身占4字节,所以留给b的开始地址也是4字节对齐地址,所以b可以直接放(b的位置就决定了a一共占4字节,因为不需要填充)b的起始地址定了以后,结束地址不能定(因为可能需要填充),结束地址要看下一个元素来定。然后是第三个元素c,short类型需要两字节对齐(short类型元素必须放在类似0,2,4,8这样的地址处,不能放在1,3这样的奇数地址处),因此c不能紧挨着b来存放,解决方案是在b之后添加1字节的填充,然后再开始放c。c放完之后还没结束,当整个结构体的所有元素都对齐存放之后,还没结束,因为整个结构体的大小还要是4的整数倍。(32位电脑,4字节对齐)
gcc支持但不推荐的对齐指令:#pragma pack() #pragma pack(n) (n=1/2/4/8)
  1. #pragma使用来指挥编译器,或者说设置编译器的对齐方式的,编译器默认是4,但有事不希望4字节对齐,而希望是别的,
  2. #pragma pack(),这种就是设置编译器1字节对齐(不对齐,取消编译器对齐访问)
  3. #pragma pack(n) (n=1/2/4/8),括号中的数字就是我们希望多少字节对齐
  4. 我们需要#pragma pack(n) 开头,以#pragma pack()结尾,定义一个区间, 这个区间内的对齐参数就为n
  5. #pragma pack(n) 方式的对齐指令在很多C环境下都是支持的,gcc虽然可以但是不建议
  6. gcc推荐的对齐指令__attribute_((packed)) _attribute((aligned))

共用体union
  1. 共用体和结构体在类型、结构、定义变量、使用方法上很相似
  2. 共用体中的各个成员是一起的,使用同一个单元。结构体各个成员是彼此独立的,只是被打包成了一块包裹。
  3. 共用体只是一个内存空间的不同解析方式。
  4. union的大小是各元素里面占用内存最大的那个,不涉及内存对齐。
union和struct的异同
  1. 操作语法相同
  2. 本质不同,struct是多个不同的元素在一起打包成一个。union是一个元素的多种解析方式。
union主要用途
  1. union就用在对一个内存单元进行多种不同规则解析的情况下。
  2. C语言中union完全可以用struct+pointer代替union,但是union更简单。
    union中a和b都是从u1的低地址开始访问的,假设u1所在的四字节分别是1、2、3、4的话,那么a自然就是1、2、3、4。b所在的地址是1而不是4
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值