C语言-结构体与位域

1. 结构体介绍 c语言里的结构体是可以包含不同数据类型和相同数据类型的一个有序集合,属于构造类型,可以自己任意组合,并且结构体里也可以使用结构体类型作为成员。
结构体在项目开发中使用非常多,无处不在,有了结构体类型就可以设计很多框架,模型,方便数据传输,存储等等。
结构体定义语法
struct 结构体名称{ 数据类型1 成员名1; 数据类型2 成员名2; 数据类型3 成员名3; .....};结构体的名称命名规则: 和普通变量命名规则一样—遵循c语言变量命名标准。 ‘a’~‘z’ ‘a’~ ’z’ ‘0’~’9’ _ 示例代码:
struct app{ int age; //年龄 char name[100]; //姓名 int number; //学号};上面这一块代码表示定义(声明)一个新的结构体类型。 数据类型名称:struct app 2. 如何使用结构体定义变量? 结构体定义变量有3种形式:
#include //第一种形式:在定义结构体类型的时候同时定义变量struct app1{ int age; //年龄 char name[100]; //姓名 int number; //学号}a1,a2,a3; //a1 a2 a3就是定义的结构体变量//第二种形式struct app2{ int age; //年龄 char name[100]; //姓名 int number; //学号};//第三种形式: 匿名方式定义结构体struct{ int age; //年龄 char name[100]; //姓名 int number; //学号}c1,c2,c3; //c1 c2 c3就是定义的结构体变量int main(){ //使用结构体类型定义变量 struct app2 b1; struct app2 b2; struct app2 b3; return 0;} 3. 结构体的赋值 结构体变量的赋值语法:
结构体变量名.成员名=xxx; 结构体初始化赋值说明:
结构体只能在(定义结构体变量的时候)初始化的时候支持整体赋值,之后就只能按照成员单个赋值。
注意:结构体变量之间支持直接赋值。
#include #include //第一种形式:在定义结构体类型的时候同时定义变量struct app1{ int age; //年龄 char name[100]; //姓名 int number; //学号}a1={23,小白,5678},a2,a3={12,小明,1234}; //a1 a2 a3就是定义的结构体变量//第二种形式struct app2{ int age; //年龄 char name[100]; //姓名 int number; //学号};int main(){ //使用结构体类型定义变量 struct app2 b1={15,小李,6878}; struct app2 b2; struct app2 b3; //单个修改结构体成员变量的值 b1.age=18; //b1.name=555; strcpy(b1.name,小丽); printf(b1:%d\n,b1.age); printf(b1:%s\n,b1.name); printf(a1:%d\n,a1.age); printf(a1:%s\n,a1.name); //结构体变量之间支持直接赋值 (要保证变量的类型要一致)。 //int a=100; //int b; //b=a; b2=b1; //将b1结构体变量赋值给b2结构体变量 printf(b2:%d\n,b2.age); printf(b2:%s\n,b2.name); return 0;} 4. 结构体指针定义与使用 示例代码:
#include #include #include struct app{ int age; //年龄 char name[100]; //姓名 int number; //学号}; int main(){ struct app a1; //定义一个结构体变量 struct app *p1; //定义一个结构体指针 struct app *p2; //定义一个结构体指针 p1=&a1; //地址赋值 p1指向a1的空间 //申请堆空间 p2=malloc(sizeof(struct app)); //通过指针访问成员 p1->age=20; strcpy(p1->name,小红); p1->number=1234; //输出数据 printf(姓名:%s\n,p1->name); printf(学号:%d\n,p1->number); printf(年龄:%d\n,p1->age); //通过指针访问成员 p2->age=13; strcpy(p2->name,小李); p2->number=5678; //输出数据 printf(姓名:%s\n,p2->name); printf(学号:%d\n,p2->number); printf(年龄:%d\n,p2->age); //释放空间 free(p2); return 0;} 5. 结构体数组定义与使用 示例代码:
#include #include #include struct app{ int age; //年龄 char name[100]; //姓名 int number; //学号}; int main(){ //定义一个结构体数组 struct app buff[10]; //一次定义了10个结构体变量 struct app *p=buff; //定义一个结构体指针 //访问成员 buff[0].age=10; strcpy(buff[0].name,小米); buff[0].number=1234; //打印数据 printf(姓名:%s\n,buff[0].name); printf(学号:%d\n,buff[0].number); printf(年龄:%d\n,buff[0].age); printf(姓名:%s\n,p[0].name); printf(学号:%d\n,p[0].number); printf(年龄:%d\n,p[0].age); return 0;} 6. 结构体当做函数的形参和返回值 示例代码:
#include #include #include struct app{ int age; //年龄 char name[100]; //姓名 int number; //学号}; struct app *func_stu(struct app *p);int main(){ //定义一个结构体数组 struct app buff[10]; //一次定义了10个结构体变量 //调用函数 func_stu(&buff[0]); //打印数据 printf(姓名:%s\n,buff[0].name); printf(学号:%d\n,buff[0].number); printf(年龄:%d\n,buff[0].age); return 0;}//定义函数struct app *func_stu(struct app *p){ //访问成员 p->age=10; strcpy(p->name,小米); p->number=1234; return p;} 7. typedef关键字在结构体里使用方法#include #include #include typedef struct app{ int age; //年龄 char name[100]; //姓名 int number; //学号}stu; //stu叫结构体类型,相当于struct app的别名。 struct app == stustu *func_stu(stu *p);int main(){ //定义一个结构体数组 stu buff[10]; //一次定义了10个结构体变量 //调用函数 func_stu(&buff[0]); //打印数据 printf(姓名:%s\n,buff[0].name); printf(学号:%d\n,buff[0].number); printf(年龄:%d\n,buff[0].age); return 0;}//定义函数stu *func_stu(stu *p){ //访问成员 p->age=10; strcpy(p->name,小米); p->number=1234; return p;} 8. 结构体位域 位域用的不多,但是也有地方使用,主要是节省空间。
#include struct app{ unsigned int a:12; //定义位域,指定位宽 12的单位是位 unsigned int b:16; unsigned char c:1; //定义空间存储1位的数据。 1和0 unsigned int :5; //位域的名称可以省略掉,为了空间内存对齐而存在的};/*1. 位域的大小不能超出本来数据类型大小。2. 位域的名称可以省略掉,为了空间内存对齐而存在的3. 位域的成员无法取地址操作*/int main(){ struct app data; //data.c=2; 错误 超出范围 只能存放0~1 //data.b=65535; 错误 超出范围 只能存放0~65535 // data.a=4096; 错误 超出范围 只能存放0~65535 //printf(%d\n,data.c); // printf(%d\n,data.b); //printf(%d\n,data.a); //printf(%d\n,&data.a); //错误 位域的成员无法取地址操作 data.c=1; data.b=555; //只能存放0~65535 data.a=888; //只能存放0~65535 printf(%d\n,data.c); printf(%d\n,data.b); printf(%d\n,data.a); return 0;} 9. 结构体的内存对齐 9.1 示例1: 计算结构体内存对齐#include struct app{ int a1; char a2; char a3; char a4; char a5; char a6; char a7;};/*目前32位系统里,使用的是gcc编译器。开空间的对齐原理:以结构体里出现的最大数据类型的倍数开空间,最大是4个字节。*/int main(){ struct app data; printf(空间大小:%d 字节\n,sizeof(struct app)); //8 return 0;}//func(1,1123,45,45,123.45,'a');void func(char *p,...){} 9.2 示例2: 计算结构体内存对齐#include #if 0struct app{ char a1; //1 short a2; //2};最终占用空间大小4个字节#endif#if 0struct app{ int a1[10]; //4*10=40 char a2[10]; //12 int a3; //4 float a4; //4 char a5; //4};//最终占用空间大小64个字节#endif#if 1struct app{ int a1; double a2;};//最终占用空间大小64个字节#endif/*目前32位系统里,使用的是gcc编译器。开空间的对齐原理:以结构体里出现的最大数据类型的倍数开空间,最大是4个字节。*/int main(){ struct app data; printf(空间大小:%d 字节\n,sizeof(struct app)); //8 return 0;}//func(1,1123,45,45,123.45,'a');void func(char *p,...){} 9.3 输出结构体变量成员的地址,查看空间对齐情况#include struct app{ int a1[10]; //4*10=40 char a2[10]; //12 int a3; //4 float a4; //4 char a5; //4};//最终占用空间大小64个字节int main(){ struct app data; //输出地址 查看空间对齐原理 printf(%#x\n,data.a1); printf(%#x\n,data.a2); printf(%#x\n,&data.a3); printf(%#x\n,&data.a4); printf(%#x\n,&data.a5); return 0;} 9.4 对齐结构体进行强制对齐#include #pragma pack(1) //1 2 4 8struct app{ int a1[10]; //4*10=40 char a2[10]; //1*10=10 int a3; //4 float a4; //4 char a5; //1};int main(){ struct app data; //输出地址 查看空间对齐原理 printf(%#x\n,data.a1); printf(%#x\n,data.a2); printf(%#x\n,&data.a3); printf(%#x\n,&data.a4); printf(%#x\n,&data.a5); printf(%d\n,sizeof(struct app)); return 0;}
诺基亚出售逾450项专利给专利授权公司Sisvel
专访韩国区块链企业CONUN集团表世镇议长
Cortex-M0/M0+/M3/M4处理器是什么鬼?
提升机结构是如何组成的
DC/DC评估篇损耗探讨-损耗的简单计算方法
C语言-结构体与位域
什么是超导数字集成电路呢?超导数字集成电路的基本知识
湖南纽恩驰团队研发可远程驾驶系统的新能源车
项目Q究竟是骗局还是新的比特币
小米11即将首发:搭载高通骁龙888
苹果Xs和三星Note9哪个更值得买
是德科技推出面向移动运营商的 5G 解决方案
XR将成为驱动下一次变革的重要平台,高通推动XR生态协同发展
蓝牙芯片解决方案市场规模的简单分析
Nuraphone耳机评测 聆听音乐的全新方式
智芯科微发布AT610x深度学习语音识别芯片
大疆最新推出FPV无人机,自带“人机合一”效果
在氮化镓外延结构中首次实现了垂直沟道结型场效应晶体管
大会回顾 | 重温第四届全国热应力大会安泰电子高光时刻!
PLC梯形图如何绘制