自定义类型:结构体、枚举、联合

本文详细介绍了C语言中的结构体与联合的概念及其使用方法,包括结构体的定义、初始化、成员访问、内存对齐及位段等知识点,并通过实例讲解了结构体与联合的应用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

结构体:

所谓结构体,就是将一大堆值放在一起,创建一个新的类型,这些成员可以是不同类型的变量。

struct tag
{
member-list;
}variable-list;

tag:   要求:1.见名知意; 2.可以省略; 3.不建议省略;

member-list: C语言中,不能为空;

variable-list: 变量列表,可以省略,建议省略;

结构体之间不能互相复制;例如:

struct 
{
 int a;
 char b
 float c;
}x;
struct
{
 int a;
 char b;
 float c;
}a[20],*p;

p = &x;    (错误!)

结构体地址 = 首元素地址(在数值上)

结构体内元素地址递增;

结构体成员访问:

结构体变量的成员是通过点操作符(.)访问的;

例如:

struct
{
 char name[20];
 int age;
};
struct S s
strcpy(s.name,"zhangsan");
s.age = 20;

或者用指针访问:

(*p).a =

  (*p).b =

或:

p->a =

p->b =

void print(struct S* ps)
{
 printf("name = %s",(*ps).name);
 printf("name = %s",ps->name);
}

结构体的自引用:

正确方式(必须用指针):

struct Node
{
 int data;
 struct Node* next;
};

也可以对结构体进行重命名:

typedef ……

结构体的不完整声明,结构体之间可以互相引用吗,答案是肯定的,不过,要提前声明才行;

struct B
struct A
{
 int _a;
 struct B* pb;
};
struct B
{
 int _b;
 struct A* pa;
};

结构体与数组一样,不能被整体赋值,但可以被初始化;

结构体的内存对齐:

即结构体的大小计算:

首先,了解一下对齐规则:

1.第一个成员在与结构体变量偏移量0的地址处;

2.其他成员变量要对其到某个数字(对齐数)的整数倍的地址处。对齐数=编译器默认的一个对齐数与该成员大小的较小值。(VS中默认的值是8,linux中默认的值是4)

3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍;

4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍;

那为什么存在内存对齐呢?

1.平台原因(移植原因):

2.性能原因:

总之,结构体对齐是拿空间来换取时间的做法;

修改对齐数:

#pragma pack( )——修改默认对齐数;

设置为1,2,4,8……

空白表示恢复默认;

结构体传参:

结构体传参不发生降维,不过,结构体传参尽量不传结构体变量,而传结构体指针;

struct S
{
 int data[1000];
 int num;
};
struct S s = {{1,2,3,4},1000};
void print(struct S* ps)
{
 printf("%d\n",ps->num);
}
int main()
{
 print(&s);
 return 0;
}

位段:

1.位段的成员必须是 int unsigned int 或singed int

2.位段的成员名后边有一个冒号和一个数字;

比如:

struct A
{
 int _a:2;
 int _b:5;
 int _c:10;
 int _d:30;
};

这个数字表示 占用的byte位

位段采用压缩存储;

位段的内存分配:

1.位段的类型可以是int  unsigned int  signed int 或者是 char 类型;

2.位段上的空间是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的;

3.位段涉及很多不确定因素,位段是不跨平台的,注重可移植性的程序应该避免使用位段;

位段的跨平台问题:

1.int 位段被当成有符号数还是无符号数是不确定的;

2.位段中最大位的数目不能确定(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题。)

3.位段中的成员在内存中从左向右分配还是从右向左分配,标准尚未定义;

4.当一个结构包含两个位段,第二个位段成员比较大,无法容纳第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的;

枚举:

枚举——顾名思义就是一一列举;

枚举内的内容都是常量;

例如:

enum Day //星期
{
   Mon,
   Tues,
   Wed,
   Thur,
   Fri,
   Sat,
   Sun
};

这些枚举{ }中的内容是枚举类型的可能取值,也叫枚举常量,这些可能取值都是有值的,默认从0开始,依次递增1,当然也可以自行赋值;

枚举的优点:

1.增加代码的可读性和可维护性;

2.和#define定义的标识符比较枚举有类型检查,更加严谨;

3.防止了命名污染;

4.便于调试;

5.使用方便,一次可以定义多个常量;

联合:

联合的成员是共用同一块内存空间的,所以一个联合体的大小,至少是最大成员的大小;

例如:面试题 判断当前计算机的大小端;

union Un
{
  int i;
  char c;
};
union un;
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n",un.i);

运行上述代码,若输出结果为55223344,则该计算机为小端,若输出结果为11223355;则该计算机为大端;

联合大小计算:

联合体的大小至少是最大成员的大小;

当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍;

联合体和结构体的巧妙运用:

//将long类型的IP地址,转换为点分十进制的表示形式;

union ip_addr
{
  unsigned long addr;
  struct
  {
    unsigned char c1;
    unsigned char c2;
    unsigned char c3;
    unsigned char c4;
  }ip;
};

union ip_addr my_ip;
my_ip.addr = 176238749;
printf("%d.%d.%d.%d\n",my_ip.ip.c4,my_ip.ip.c3,my_ip.ip.c2,my_ip.ip.c1);









基于Spring Boot搭建的一个多功能在线学习系统的实现细节。系统分为管理员和用户两个主要模块。管理员负责视频、文件和文章资料的管理以及系统运营维护;用户则可以进行视频播放、资料下载、参与学习论坛并享受个性化学习服务。文中重点探讨了文件下载的安全性和性能优化(如使用Resource对象避免内存溢出),积分排行榜的高效实现(采用Redis Sorted Set结构),敏感词过滤机制(利用DFA算法构建内存过滤树)以及视频播放的浏览器兼容性解决方案(通过FFmpeg调整MOOV原子位置)。此外,还提到了权限管理方面自定义动态加载器的应用,提高了系统的灵活性和易用性。 适合人群:对Spring Boot有一定了解,希望深入理解其实际应用的技术人员,尤其是从事在线教育平台开发的相关从业者。 使用场景及目标:适用于需要快速搭建稳定高效的在线学习平台的企业或团队。目标在于提供一套完整的解决方案,涵盖从资源管理到用户体验优化等多个方面,帮助开发者更好地理解和掌握Spring Boot框架的实际运用技巧。 其他说明:文中不仅提供了具体的代码示例和技术思路,还分享了许多实践经验教训,对于提高项目质量有着重要的指导意义。同时强调了安全性、性能优化等方面的重要性,确保系统能够应对大规模用户的并发访问需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值