7 结构体、共用体和枚举

结构体概述

1 结构体使用时先定义结构体类型,再用类型定义变量
2 结构体变量中的元素访问方式只有一种,用句点.或者箭头->。
3 结构体的对齐访问

访问结构体时需要对齐访问,主要是配合硬件,也就是说硬件硬件本身有物理上的限制,因此对齐排布和访问可以提高访问效率,对齐访问牺牲了内存,但换取了速度性能。
对齐访问的规则和运算
(1)当编译器将结构体设置为4字节对齐时,结构体整体必须从4字节对齐处存放,结构体对齐后的大小必须为4的倍数。如果编译器设置为8字节对齐,这里的4就是8.
(2)结构体中每个元素本身也必须对齐存放;
(3)编译器在考虑以上两点情况下,实现以最少内存来开辟结构体空间。
手动对齐
需要以#pragma pack(n)开头,以#pragma pack()结尾,定义一个区间,这个区间内的对齐参数是n。
GCC推荐的对齐指令
_ attribute _((packed)) 和 _ attribute _((aligned(n)))
直接放在类型定义的后面,那么该类型就以指定的方式进行对齐,packed的作用就是取消对齐,aligned(n)表示对齐方式。

offsetof宏与container_of宏

offsetof宏

计算结构体中某个元素相对结构首字节地址的偏移量,其实质是通过编译器来计算的。

container_of宏

作用:知道一个结构体中某个成员的指针,反推这个结构体变量的指针。
typeof关键字的作用:通过typeof(a)由变量a 得到a的类型,由变量名得到变量的数据类型。
工作原理:先用typeof得到member成员的类型,将member成员的指针转成自己类型的指针,然后用这个指针将去该成员相对于整个结构体变量的偏移量(偏移量用offsetof宏得到),之后得到就是整个结构体变量的首地址,再把这个地址强制类型转换为type* 即可。

共用体(union)

(1)共用体和结构体在类型声明、变量定义和使用方法相似;
(2)结构体中的成员彼此独立,分布在内存的不同单元中;共用体中的各个成员是一体的,使用的是同一内存单元;
(3)共用体的sizeof测试的大小实际是共用体中各个元素里面占用内存最大的元素大小;
(4)共用体不存在内存对齐,只有一个内存空间,从同一地址(就是整个共用体占有的内存空间的首地址)开始。
(5)主要对同内存单元进行多种不同规则解析

大小端模式

大端模式:高字节对应地地址;
小端模式:高字节对应高地址;
理论上按照大小端模式都可以,但是要求存储和读取时必须按照同样的大小端模式来进行。否则会出错。
测试当前机器的大小端模式

#include<stdio.h>
//共用体中很重要的一点a和b都是从u1的地地址开始的
//假设u1所在的4字节地址分别是:0、1、2、3
//那么a自然就是0、1、2、3;b所在的地址是0而不是3
union myunion
{
    int a;
    char b;
};
//如果小端模式则返回1,大端模式则返回0
int is_little_endian(void)
{
    union myunion u1;
    u1.a = 1;
    return u1.b;
    //int a = 1;
    //char b = * ((char *)(&a));
    //return b;
}
int main (void)
{

    int i = is_little_endian();
    if (1 == i)
    {
        printf("小端模式\n");
    }
    else
    {
         printf("大端模式\n");

    }
    return 0;
}

枚举(enum)

使用枚举其实就是对1、0这些数字进行符号化编码,这样的好处是编程时可以不用看数组而直接看符号。枚举是将多个有关联的符号封装在一个枚举中,而宏定义是完全分散的,当我们定义是一个有限集合时,适合用枚举。
在一个文件汇总不能有两个或者两个以上的enum被typedef成相同的别名;
enum成员的访问方式是成员名,不能有重名的枚举成员;但是两个#define宏定义是可以重名的,该宏名真正的值取决于最后一次定义的值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值