返回

结构体进阶

发布时间:2022-09-20 07:20:03 384
# 数据
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include


//声明一个结构体类型
//声明一个学生类型,是通过学生类型来创建学生变量(对象)
//描述学生:属性-名字+电话+性别+年龄
//
//struct stu
//{
// char name[20];
// char tele[12];
// char sex[10];
// int age;
//}s4;//全局变量
//
//struct stu s3;//全局变量
//
//int main()
//{
// //创建的结构体变量
// struct stu s1;
// struct stu s2;
// return 0;
//}


//匿名结构体
//struct
//{
// int a;
// char b;
// float c;
//}x;
//struct
//{
// int a;
// char b;
// float c;
//}*p;
//上面两个结构体在声明的时候省略了结构体标签
//那么p=&a合法吗?
//编译器会把上面的两个声明当成完全不同的两个类型,所以是非法的。


//结构体自引用
//typedef struct Node
//{
// double d;
// int date;
// struct Node* next;
//}Node;
////typedef把struct Node类型重命名为Node
//int main()
//{
// struct Node n1;
// Node n2;
// return 0;
//}


//结构体变量的定义和初始化
//struct point
//{
// int x;
// int y;
//}p1; //声明类型的同时定义全局变量P1
//struct point p2; //定义结构体变量p2
//struct point p3 = { 5,10 }; //初始化:定义变量的同时赋初值
//
//struct T
//{
// double weight;
// short age;
//};
//struct S
//{
// char c;
// struct T st;
// int a;
// double d;
// char arr[20];
//};
//int main()
//{
// struct S s = { 'c',{3.14,20},200,4.5,"hello world" }; //定义结构体变量并赋初始值
// printf("%c %lf %hd %d %lf %s\n", s.c, s.st.weight, s.st.age, s.a, s.d, s.arr);
// return 0;
//}


//结构体内存对齐
//结构体对齐规则:
//1.第一个成员在与结构体变量偏移量为0的地址处。
//2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
// 对齐数=编译器默认的一个对齐数 与 该成员大小的较小值。(VS默认为8)
//3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
//4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的
// 整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
//
//struct S1
//{
// char c1;
// int a;
// char c2;
//};
//struct S2
//{
// char c1;
// char c2;
// int a;
//};
//struct S3
//{
// double d;
// char c;
// int i;
//};
//struct S4
//{
// char c;
// struct S3 s3;
// double d;
//};
//int main()
//{
// struct S1 s1 = { 0 };
// struct S2 s2 = { 0 };
// struct S3 s3;
// struct S4 s4;
// printf("%d\n", sizeof(s1));
// printf("%d\n", sizeof(s2));
// printf("%d\n", sizeof(s3));
// printf("%d\n", sizeof(s4));
// return 0;
//}
//为什么存在内存对齐?
//1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能
// 在某些地址处取某些特定类型的数据,否则抛出硬件异常。
//2.性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐
// 的内存,处理器需要作两次内存访问,而对齐的内存访问仅需要一次访问。
//总体来说:
// 结构体的内存对齐是拿空间来换取时间的做法。
//
//在设计结构体的时候,我们既要满足对齐,又要节省空间,要让占用空间小的成员尽量集中在一起。
//例如上面的S1和S2类型的成员一模一样,但是S1和S2所占空间的大小有了一些区别。


//修改默认对齐数
//
//设置默认对齐数
//#pragma pack(4)
//struct S
//{
// char c1;
// double d;
//};
//#pragma pack()
////取消设置的默认对齐数
//
////#pragma pack(2)
////struct S1
////{
//// char c1;
//// double d;
////};
////#pragma pack()
//int main()
//{
// struct S s;
// //struct S1 s1;
// printf("%d\n", sizeof(s));
// //printf("%d\n", sizeof(s1));
// return 0;
//}


//offsetof(宏)--计算结构体成员相对于结构体起始位置的偏移量
//#include
//struct S
//{
// char c;
// int i;
// double d;
//};
//int main()
//{
// printf("%d\n", offsetof(struct S, c));
// printf("%d\n", offsetof(struct S, i));
// printf("%d\n", offsetof(struct S, d));
// return 0;
//}


//结构体传参
//struct S
//{
// int a;
// char c;
// double d;
//};
//void Init(struct S* ps)
//{
// ps->a = 100;
// ps->c = 'w';
// ps->d = 3.14;
//}
////传值
//void Print1(struct S tmp)
//{
// printf("%d %c %lf\n", tmp.a, tmp.c, tmp.d);
//}
////传址(推荐)
//void Print2(const struct S* ps)
//{
// printf("%d %c %lf\n", ps->a, ps->c, ps->d);
//}
//int main()
//{
// struct S s = { 0 };
// /*s.a = 100;
// s.c = 'w';
// s.d = 3.14;
// printf("%d %c %lf\n", s.a, s.c, s.d);*/
// Init(&s);
// Print1(s);
// Print2(&s);
// return 0;
//}
//函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。如果传递一个结构体
//对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下将。
//所以结构体传参的时候,要传结构体的地址。
特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
学习C语言的第四天 2022-09-20 06:31:36