结构体:

描述一个学生:
struct Stu
{char name[20];//名字int age;//年龄char sex[5];//性别char id[20];//学号
};//分号不能丢
特殊的声明
//匿名结构体类型
struct
{int a;char b;float c;}x;
struct
{int a;char b;float c;
}a[20], *p;
在上面代码的基础上,下面的代码合法吗?
p = &x;
警告:
编译器会把上面的两个声明当成完全不同的两个类型。 所以是非法的。

创建结构体变量:


struct stu
{int a;char b;float c;
}s4,s3,s5;//全局变量struct stu s6;//全局变量int main()
{
struct stu s7;//局部变量
}

如果在结构体内部存了一个结构体如下所示:

这样的结果是什么,会无限大。因为每个结构体里面都存了一个整型。

数据结构链表的正确打开方式,存指针。 如下所示。

结构体的打印回顾: 

复合结构体打印:

 结构体内存对齐

举个例子:

//例如:
struct S1
{char c1;//0,占了一个字节int i;//对齐数4,8。取4 ,对齐到偏移4的位置,4个字节char c2;//占了一个字节。
};
总共9个字节,最大对齐数的整数倍是12个字节
struct S2
{char c1;//占用一个字节char c2;//占用一个字节int i;//对齐数4,8。取4 ,对齐到偏移4的位置,4个字节
};
总共占用8个字节。
struct S3
{double d;//占用8个字节。char c;//占用1个字节。int i;//对齐数是4,从偏移12字节开始,占用四个字节
};
printf("%d\n", sizeof(struct S3));//总共16字节,恰好是4的整数倍。结构体嵌套问题
struct S4
{char c1;//占用一个字节struct S3 s3;//从偏移8个字节处开始对齐,占用16个字节。double d;//从偏移24字节处对齐,占用8字节
};
printf("%d\n", sizeof(struct S4));//总共占用32字节。是8的整数倍。

为什么有对齐数?

如果是32位的机器,那么一次性访问四个字节。没有对齐数。如上图的a,访问四个字节只访问了一部分 。

#pragma pack()//取消设置的默认对齐数,还原为默认

计算某个参数偏移的字节数:

这是一个宏,不是一个函数。

 结构体传参:

struct S {int data[1000];int num;
};
struct S s = {{1,2,3,4}, 1000};
//结构体传参
void print1(struct S s) {printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps) {printf("%d\n", ps->num);
}
int main()
{print1(s);  //传结构体print2(&s); //传地址return 0; }
上面的 print1 和 print2 函数哪个好些?
答案是:首选print2函数。 原因:
函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。
如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能
的下降。
结论:
结构体传参的时候,要传结构体的地址。
位段:位段的声明和结构是类似的,有两个不同:
1.位段的成员必须是 int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字。
比如:
struct A {int _a:2;int _b:5;int _c:10;int _d:30;
};//A就是一个位段类型。printf("%d\n", sizeof(struct A));
那位段A的大小是多少?答案是8字节.
//占用了47个bit,按理需要6个字节即可。

位段的内存分配

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

以上位段是按照4个字节来开辟的,a,b总共占用1个字节,接着可以存放c,再存放d。但是存放d的时候4个字节装不下了,所以要另外开辟4个字节。所以以上位段的大小是8字节。

//一个例子
struct S {char a:3;char b:4;char c:5;char d:4;
};
struct S s = {0};
s.a = 10; s.b = 12; s.c = 3; s.d = 4;
//空间是如何开辟的?

首先存a,但是a只存了3个比特位。再存b的4个比特位。等到存放c的时候,一个字节装不下了,另外开辟一个字节存放c,存不下d再另外开辟一个字节存放d。总共占用3个字节。(只放前面几个,不够的话前面补0,多余的舍去。)

枚举
枚举顾名思义就是一一列举。
把可能的取值一一列举。
enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};
enum Sex//性别
{MALE,FEMALE,SECRET
};
enum Color//颜色
{RED,GREEN,BLUE
};
以上定义的 enum Day , enum Sex , enum Color 都是枚举类型。 {}中的内容是枚举类型的可能取值,也叫 枚举常量 。

这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。 例如:

enum Color//颜色
{RED=1,GREEN=2,BLUE=4
};
枚举的优点
为什么使用枚举?
我们可以使用 #define 定义常量,为什么非要使用枚举?
枚举的优点:
1. 增加代码的可读性和可维护性
2. 和#defifine定义的标识符比较枚举有类型检查,更加严谨。
3. 防止了命名污染(封装)
4. 便于调试
5. 使用方便,一次可以定义多个常量
枚举变量的定义: 

枚举的打印:

打印出来的是0,1,2.

联合类型的定义
联合也是一种特殊的自定义类型 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块
空间(所以联合也叫共用体)。
//联合类型的声明
union Un
{char c;int i;
};
//联合变量的定义
union Un un;
//计算连个变量的大小
printf("%d\n", sizeof(un));
联合的特点
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为
联合至少得有能力保存最大的那个成员)

先看下面一个现象:发现c和i的地址是一样的。

 例题:判断当前计算机的大小端存储

方法一:

方法二:改进检查函数

因为之前我们看了联合体里面的地址是一样的,所以返回第一个即可。

联合大小的计算
联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

本来是5个字节,但是最大对齐数是4,所以是8;

枚举大小的计算:拿刚才的例子(他们都是整型,所以大小是4)

自定义类型:结构体,枚举,联合相关推荐

  1. 【C语言】自定义类型 结构体 枚举 联合

    结构体的基础知识 结构体是一些值的集合,这些值称为成员变量.结构体的每个成员可以是不同类型的变量. 结构体的声明 定义一个学生的结构体 struct Stu {char name[20];//名字in ...

  2. 自定义类型:结构体2.0(初阶+进阶)+位段+枚举+联合

    目录 一.结构体

  3. 【结构体——枚举——联合】

    文章目录 前言 结构体 结构体类型的声明 结构的自引用 结构体变量的定义和初始化 结构体内存对齐 修改默认对齐数 结构体传参 结构体实现位段(位段的填充&可移植性) 枚举 枚举类型的定义 枚举 ...

  4. 结构体枚举联合详解(附例题解析)

    目录: 结构体的初始化 结构体的内存对齐 位段 -->位段的内存分配 -->位段的跨平台问题 枚举的优点 联合的特点 联合体的大小计算 结构体的初始化 struct Stu {char n ...

  5. C语言--自定义类型——结构体

    结构体 建立结构体声明 定义结构变量 初始化结构 访问结构体成员 结构的初始化器 结构数组 指向结构的指针 用指针访问成员 向函数传递结构的信息 传递结构成员 传递结构的地址 传递结构 结构和结构指针 ...

  6. C语言自定义变量类型——结构体详解

    文章目录 前言 为什么要学习结构体 什么是结构体 一.结构体:struct 1.结构体类型的声明 (1)结构体的基础知识 (2)结构体的声明 (3)特殊的声明 2.结构体的自引用 3.结构体变量的定义 ...

  7. C语言 | 【耗费一夜总结三本C语言系列】之 结构体、联合、枚举

    前言 本章内容总结了结构体.联合.枚举,对于结构体总结了结构体指针用法,参数传递,内存对齐等较为重要的知识点. C语言 | 快速了解C的发展史

  8. 结构体+枚举+联合体

    结构体+枚举+联合体 结构体 结构体的声明 结构体的嵌套+链表 结构体变量的初始化 结构体的内存对齐 一.首先得掌握结构体的对齐规则 二.一些具体的例子 为什么存在内存对齐? 位段 位段的内存保存 枚 ...

  9. 自定义数据类型——结构体

    结构体的定义与使用 数组是一种数据形式,其特点是多个相同类型的元素集合起来 结构体是另一种重要的数据形式,特点是将不同类型的成员组合起来 数组和结构体形成了两种风格迥异的聚合方式,通过他们以及相互组合 ...

  10. 同类型结构体之间赋值不一定有效

    同类型结构体之间赋值不一定有效 今天为这个问题debug好久... 之前看到一个关于结构体使用的技巧, 这个技巧可以避免内存零碎. 保证结构体所属内存尽量不要零散化. struct struct_na ...

最新文章

  1. JS contcat() 连接数组 函数
  2. Store Kit Guide(In App Purchase)翻译
  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(4)-创建项目解决方案
  4. scanf_s 发送访问冲突_程序员如何解决并发冲突的难题?
  5. 辅助出售网站源码_出售网站意味着出售社区
  6. java static final关键字_Java的static与final关键字
  7. AndroidStudio安卓原生开发_fragment与activity双向通信_3种方式---Android原生开发工作笔记118
  8. SpringMVC学习指南-前言
  9. WebLogic部署项目成功后,访问Error 404
  10. 内网渗透-域管理员定位
  11. 夏普Sharp AR-163N 一体机驱动
  12. nodejs+vue+elementui企业考勤管理系统
  13. Windows命令之ftp命令
  14. 单基因gsea_JTO:日本Smoker基因组综合分析
  15. iOS 【iOS-切换控制器的手段及异同】
  16. 常见关系型数据库(sql server/oracle)查询语句面试题
  17. south的使用总结
  18. 拼多多商家如何运营好店铺?商家如何一键打单?
  19. C语言-全局变量与局部变量
  20. 微信网页开发:微信内h5使用wx-open-launch-weapp打开小程序,微信内h5使用wx-open-launch-app打开App的方案

热门文章

  1. DQN神经网络小结(Pytorch版)
  2. SAP 深入理解销售订单
  3. mysql 禁用事件_mysql事件之修改事件(ALTER EVENT)、禁用事件(DISABLE)、启用事件(ENABLE)、事件重命名及数据库事件迁移操作详解...
  4. 针对Android TV端使用的自定义RecyclerView
  5. 聚划算十周年被赋予新使命: 满足消费者新需求 提升供给侧效率
  6. python open找不到文件的原因_浅谈python 调用open()打开文件时路径出错的原因
  7. 计算机相关的队名,有创意的队名和口号(精选80个)
  8. python pickle反序列化漏洞_Python反序列化漏洞
  9. 设置/恢复系统隐藏文件 - Windows系统
  10. 程序人生:初学者中最最最常问的问题都有哪些呢???