曲靖住房和城乡建设局网站,python网站开发效率,甬城通可以在线充值吗,购物网站建设实战教程答案文章目录 结构体结构体类型的声明特殊的声明 结构的自引用结构体变量的定义和初始化结构体内存对齐为什么要内存对齐结构体传参结构体实现位段#xff08;位段的填充可移植性#xff09;位段位段的内存分配空间如何开辟位段的跨平台问题位段的应用 枚举枚举类型的定义枚… 文章目录 结构体结构体类型的声明特殊的声明 结构的自引用结构体变量的定义和初始化结构体内存对齐为什么要内存对齐结构体传参结构体实现位段位段的填充可移植性位段位段的内存分配空间如何开辟位段的跨平台问题位段的应用 枚举枚举类型的定义枚举的优点枚举的使用 联合体联合类型的定义联合的特点联合大小的计算 c中有内置类型也有自定义类型 自定义类型有结构体 联合体 枚举 结构是一些值的集合这些值称为成员变量。结构的每个成员可以是不同类型的变量。 就像之前学过的数组一样一组相同类型元素的集合 结构体
结构体类型的声明 struct是关键字 比如描述一个学生的信息 只是创建了结构体类型 分号不能丢 struct Stu//Stu结构体名字
{
char name[20];//结构体成员}s1,s2;//s1s2是全局变量全局还是局部取决于是在主函数之内还是之外 特殊的声明 在声明结构的时候可以不完全的声明。 匿名结构体类型 struct
{
char name[20];//结构体成员
}s1,s2只能使用一次 //匿名结构体类型
struct
{int a;char b;float c;
}x;
struct
{int a;char b;float c;
}a[20], *p;
//在上面代码的基础上下面的代码合法吗
p x会报警告因为会认为两个结构体空间不一样 非法 结构的自引用 结构体不能包含同结构体类型 能包括同结构体类型指针 比如设置链表的节点 struct Node
{
int data;
struct Node* next;
};链表就是用指针像链条一样把数据穿起来 数据结构会学 //代码3
typedef struct
{int data;
struct Node* next;
}Node;
//这样写代码可行否typedef需要结构体存在才能重新定义 而Node还没创建就已经用上了 先有鸡还是先有蛋的问题~ //解决方案
typedef struct Node
{int data;struct Node* next;
}Node;这时候Nodestruct Node 结构体变量的定义和初始化 像上面的s1 s2 Node就是定义的变量 声明类型的同时定义变量 struct Stu p2; //定义结构体变量p2 初始化 struct Point
{int x;int y;
}p1; 声明类型的同时定义变量p1
struct Point p2; 定义结构体变量p2
初始化定义变量的同时赋初值。
struct Point p3 {x, y};
struct Stu 类型声明
{char name[15];名字int age; 年龄
};
struct Stu s {zhangsan, 20};初始化
struct Node
{int data;struct Point p;struct Node* next;
}n1 {10, {4,5}, NULL}; 结构体嵌套初始化
struct Node n2 {20, {5, 6}, NULL};结构体嵌套初始化打印 .操作符直接访问 -间接访问 #define _CRT_SECURE_NO_WARNINGS
#includestdio.h
#includestdio.h
#includestring.h
#if 0
struct Stu
{//结构体成员char name[18];int age;double score;};
void set_stu(struct Stu* ps)//结构体指针变量
{strcpy(ps-name, chenyanan);//ps-name和*ps.name是一样的ps-age 18;ps-score 100.0;
}
void print_stu(struct Stu s)
{printf(%s %d %lf\n, s.name, s.age, s.score);//.操作符 结构对象.成员
}
int main()
{struct Stu s { 0 };//类型变量名即s是结构体的对象set_stu(s);//形参和实参的形式不同如果s实参未改变应传递地址print_stu(s);return 0;
}结构体内存对齐 计算偏移量 头文件includestddef.h struct S3
{double d;char c;int i;
};struct S2
{char c1;struct S3 s3;double d;
};
int main()
{printf(%d\n, offsetof(struct S2, c1));//0printf(%d\n, offsetof(struct S2, s3));//8printf(%d\n, offsetof(struct S2, d));//24printf(%d\n, sizeof(struct S2));//32
}如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整 体大小就是所有最大对齐数含嵌套结构体的对齐数的整数倍。 最大对齐数是8 为什么要内存对齐 平台原因(移植原因) 不是所有的硬件平台都能访问任意地址上的任意数据的某些硬件平台只能在某些地址处取某些特定类型的数据否则抛出硬件异常。 2. 性能原因 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于为了访问未对齐的内存处理器需要作两次内存访问而对齐的内存访问仅需要一次访 问。 总体来说 结构体的内存对齐是拿空间来换取时间的做法。 提高效率 静态区栈区也是同样的储存规则 那在设计结构体的时候我们既要满足对齐又要节省空间 如何做到 让占用空间小的成员尽量集中在一起 默认最大对齐数可以修改 #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;
}首选print2 传值调用会压栈开辟一个大空间接收数据 效率低性能下降 传址空间小地址4/8个字节 传结构体的地址 结构体实现位段位段的填充可移植性
位段 位段的声明和结构是类似的有两个不同 1.位段的成员必须是 int、unsigned int 或signed int 。 2.位段的成员名后边有一个冒号和一个数字。 struct A
{int _a:2;//_a分配2个biteint _b:5;int _c:10;int _d:30;
};位段用来节省空间 位段的内存分配 位段的成员可以是 int unsigned int signed int 或者是 char 属于整形家族类型位段的空间上是按照需要以4个字节 int 或者1个字节 char 的方式来开辟的。 3. 位段涉及很多不确定因素位段是不跨平台的注重可移植的程序应该避免使用位段。 struct A
{int _a:2;//_a分配2个byteint _b:5;int _c:10;//15//开辟四个字节32个byteint _d:30;
};47byte int 4个字节 32byte 不够用再拿四个字节 会用完剩下的15个byte还是用新开辟的byte 一个例子 struct S
{char a:3;char 8个byte剩下5char b:4;剩1char c:5;开辟一个字节是会把1byte用掉在用新开辟的byte呢还是会浪费掉呢若浪费打印的是3个字节没浪费打印2个字节char d:4;
};int main()
{
printf(%d\n,sizeof(struct S)):
return 0;
}不够字节后接下来用的是新开辟的空间 空间如何开辟 大小端是超过一个字节内存存放顺序的问题 这是在VS2022中的 位段的跨平台问题 总结 跟结构体相比位段能达到同种效果且能节省空间但有跨平台问题解决就是要能针对不同平台写不同的代码 位段的应用 在网络里传输数据的时候运用 基于网络协议写出来的网络编程是可以通信的 ip协议 枚举
枚举类型的定义 通过关键字enum来定义 基本语法 enum 枚举名{
成员1值1;
成员2值2;
...
成员n值n;
};枚举成员可以是任意标识符 但值必须是整数 作用域在定义的文件内 若想要在其他文件内使用需要包含枚举的头文件 没有指定值那默认第一个枚举成员的值为0 这里的enum没有存储到内存中相当于是模板图纸使用了才会有内存的空间分配 枚举的优点 我们可以使用 #define 定义常量为什么非要使用枚举 枚举的优点 增加代码的可读性和可维护性和#define定义的标识符比较枚举有类型检查更加严谨。 宏在预处理阶段就把值进行了替换在可执行文件中看到的也是替换之后的值不便于观察便于调试使用方便一次可以定义多个常量 枚举的使用
enum Color
{
red1;
green3;
orange6;
};
int main()
{
//使用枚举类型变量
enum Color color;
//只能拿枚举常量给枚举变量赋值才不会出现类型的差异。
colorred;
//不能color1;
} 常用在需要设置特定顺序的常量值时 比如星期月份方向等 联合体
联合类型的定义 包含一系列的成员共用同一块内存空间-共用体 联合的特点 地址相同 #define _CRT_SECURE_NO_WARNINGS
#includestdio.h
union Un
{char a;int i;}u;
int main()
{printf(%zd\n, sizeof(u));printf(%p\n, u);printf(%p\n, (u.i));printf(%p\n, (u.a));return 0;
}在同一块内存中存储不同类型 不能同时用改变一个也会改变另一个 联合大小的计算 联合的大小至少是最大成员的大小。 当最大成员大小不是最大对齐数的整数倍的时候就要对齐到最大对齐数的整数倍。 union Un1
{char c[5];int i;
};
union Un2
{short c[7];int i;
};
//下面输出的结果是什么
printf(%d\n, sizeof(union Un1));8
printf(%d\n, sizeof(union Un2));16