700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 自定义数据类型(构造体/枚举/共用体/位段)

自定义数据类型(构造体/枚举/共用体/位段)

时间:2022-04-30 18:41:44

相关推荐

自定义数据类型(构造体/枚举/共用体/位段)

结构体(struct)

结构体变量的定义

#include<stdio.h>#include<string.h>#include<ctype.h>struct MyStruct{char name[20];int age;}s4,s5,s6;//创建全局的结构体变量列表//创建结构体全局变量struct MyStruct s3;//匿名结构体struct {int st;}st;//匿名结构体类型必须直接创建一个以上全局结构体变量列表//匿名结构体指针struct {int st;}* p; //这里要注意 不能 p = &st 会报警告 因为计算机认为他俩不是一样的类型int main() {//创建结构体局部变量struct MyStruct s1;struct MyStruct s2;return 0;}

#include<stdio.h>#include<string.h>#include<ctype.h>typedef struct st {int ss;}st;//typedef给结构体从命名为 st int main() {//定义一个结构体struct st s1;st s2;return 0;}

结构体自引用

#include<stdio.h>#include<string.h>#include<ctype.h>//类似链表struct MyStruct{int a;struct MyStruct* next;};int main() {return 0;}

结构体变量的初始化和读取

#include<stdio.h>#include<string.h>#include<ctype.h>typedef struct st {int num;char arr[4];}st;//typedef给结构体从命名为 st int main() {//定义一个结构体struct st s1 = { 2,"we"};printf("%d %s \n",s1.num,s1.arr);st s2 = { 3,'e' };printf("%d %c \n", s2.num, s2.arr[0]);printf("%d %s \n", s2.num, s2.arr);return 0;}

结构体内存对齐

在设计结构体时,我们尽量将占用空间小的成员集中在一起声明(对齐时少浪费一些空间)

内存对齐的原因

平台原因 不是所有硬件平台都能访问任意地址上的数据(比如说 int 类型只能在4的倍数的内存上开始读)

性能问题 被访问的数据应该尽可能在自然边界上对齐,原因在于为了访问未对齐的内存,处理器要做两次访问,而对齐的只需要一次。

(比如32位机器每次传输4个字节 如果在中间开始存 就需要读两次)

计算规则

第一成员在结构体偏移量为0的地址处。

其他成员变量要对齐到某个数字(对齐数)的整数倍数地址处(对齐数 = 编译器默认的对齐数与该成员的大小的较小值 vs的对齐数是8没有默认对齐数的话成员的大小就是对齐数 修改默认对齐数为4 #pragma pack(4) 取消#pragma pack())

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

结构体里嵌套了结构体,嵌套的结构体对齐到自己最大对齐数的整数倍数处,结构体的总大小为最大对齐数(每一个成员变量都有一个对齐数)的整数倍

<图片来源于网络>

<图片来源于网络>

内存偏移量 offsetof()

结构体成员,相对于结构体起始位置的偏移量。

#include<stddef.h>struct MyStruct{char cc;int num;};int main() {printf("%d",offsetof(struct MyStruct, num));return 0;}

结构体传参

#include<stdio.h>#include<string.h>#include<ctype.h>//写一个方法对结构体变量进行初始化//写一个方法对结构体变量进行打印struct s{int a;char c;double d;};void Init(struct s* ps) {ps->a = 100;ps->c = 'c';ps->d = 0.3;}//结构体过大时我们不建议传结构体变量 空间过大压榨系统性能void print1(struct s ps) {printf("%d %c %lf \n", ps.a, ps.c, ps.d);}void print2(const struct s* ps) {printf("%d %c %lf \n", ps->a, ps->c, ps->d);}int main() {struct s s1 = {0};printf("%d %c %lf \n", s1.a, s1.c, s1.d);Init(&s1);print1(s1);print2(&s1);return 0;}

位段片段

位段的声明与结构体是类似的 但有两点不同

位段的成员一般必须是 signed int unsigned int (整形就行)

位段的成员变量后面会有一个冒号和数字

位段不能跨平台(不能知道整形是有符号还是无符号 不同位机器的位段大小不确定 等)

位段空间上按照4个字节(int)或者一个字节(char)的方式开辟

位段后面的数字不能大于32

位段其实就是知道了结构体每个成员变量的实际取值范围, 从而以二进制位为最小单位进行分配空间。

#include<stdio.h>#include<string.h>#include<ctype.h>struct s{int _a : 2;int _b : 5;int _c : 10;int _d : 30;};int main() {struct s s1;printf("%d",sizeof(s1)); // 2+5+10+30=47bit = 47/8=6个字节(这里需要进位) 因为是int 型所以按照4个字节开辟 在开辟时如果某个空间(4个字节)不能满足成员的需求(大小不够大)就舍弃这段未利用的空间(二进制位)去下一个空间(4个字节)进行利用,所以开辟了8个字节return 0;}

<图片来源于网络>

枚举

枚举的优点

可读性和可维护性

与#define比有类型检测 更加严谨

防止命名污染

便于调试

方便使用

#include<stdio.h>#include<string.h>#include<ctype.h>enum Sex{MALE, //0FEMALE,//1SECRET, //2Q = 20,//赋初始值20W //21};int main() {enum Sex s1 = MALE;printf("%d",sizeof(s1)); // 4return 0;}

共用体(联合体)union

共用体成员 公用一块空间,成员不能被同时使用。

公用体 大小至少是最大成员的大小,当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。

比如 int i; 大小4 对齐数 4 标准对齐数8 对齐数为 4

char[5]; 大小5 对齐数 1 标准对齐数8 对齐数为 1

实际联合体大小为 4的最小倍数8

#include<stdio.h>#include<string.h>#include<ctype.h>union un{char a;int i;};int main() {union un u1;printf("%d",sizeof(u1)); // 4return 0;}

//判断当前是大端存储还是小端存储#include<stdio.h>#include<string.h>#include<ctype.h>union MyUnion{int i;char a;};int main() {union MyUnion u1;u1.i = 1;if (u1.a == '0') {printf("大端");}else {printf("小端");}return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。