结构体的概念 方法 例题 匿名结构体 自引用 结构体内存对齐原因,方法及如何修改默认对齐数

简介: 结构体的概念 方法 例题 匿名结构体 自引用 结构体内存对齐原因,方法及如何修改默认对齐数
#include<stdio.h>
//结构体
//数组是一组相同类型的元素的集合,结构体也是一些值的集合,但是结构的每个成员可以是不同类型
//struct Book                 //b1,b2,b3,b4,b5,b6都是创建的变量
//{
//    char name[20];
//    int price;
//    char id[12];
//}b4,b5,b6;//全局变量
//int main()
//{
//    struct Book b1;
//    struct Book b2;//局部变量b1,b2,b3
//    struct Book b3;
//    return 0;
//}


声明时,可以不完全声明,如


//struct//匿名结构体类型(创建变量s)
//{
//    char c;
//    int i;
//    char ch;
//    double d;
//}s;


但是下面这种,在编译器角度是不对的,因为是两种不同的类型


//struct
//{
//    char c;
//    int i;
//    char ch;
//    double d;
//}s;
//struct
//{
//    char c;
//    int i;
//    char ch;
//    double d;
//}*ps;
//int main()
//{
//    ps = &s;
//    return 0;
//}
//结构体自引用
//struct Node//Node不能省略(不能匿名),因为此处的Node(名字)要放下一个结构体的指针
//{
//    int data;//定义数据
//    struct Node* next;//把下一个结构体的地址放在该结构体中
//    //在结构体里,不是包含同类型的结构体变量,而是包含同类型的结构体指针
//};
//int main()
//{
//    //struct N sn;是错误的,结构体不能自己包含自己
//    //在结构体里,不是包含同类型的结构体变量,而是包含同类型的结构体指针
//    return 0;
//
//}
//struct S
//{
//    char c;
//    int i;
//
//}s1,s2;
//struct B
//{
//    double d;
//    struct S s;
//    char c;
//};
//int main()
//{
//    struct B sb = { 3.14,{'w',100},'q' };// 3.140000 w 100 q
//    //结构体操作符有    .  和   ->
//    printf("%lf %c %d %c", sb.d, sb.s.c, sb.s.i, sb.c);
//    return 0;
//}
//struct S
//{
//    char c1;
//    int i;
//    char c2;
//};
//struct S2
//{
//    char c1;
//    int i;
//    double d;
//};
//struct S3
//{
//    char c1;
//    char c2;
//    int i;
//};
//struct S4
//{
//    double d;
//    char c;
//    int i;
//};
//struct S5
//{
//    char c1;
//    struct S4 s4;
//    double d;
//};
//struct S6
//{
//    char n;
//    int m;
//};
//struct S7
//{
//    int  n;
//    char m;
//};


结构体内存对齐

1.结构体的第一个成员永远都放在结构体变量在内存中存储位置的10偏移处开始

2.从第2个成员往后的所有成员,都放在上一个成员的最小倍数的整数倍的地址处

(如char c int i放置为0~3(1-3浪费掉,但是必须是int的最小倍数4倍)4~7)

(如果是上一个结构体类型,就浪费掉上一个结构体距离最近的类型的最小倍数)---参见s5

3.结构体的总大小是结构体的所有成员的对齐数的整数倍

注意:放在前放在后都一样


//int main()
//{
//    struct S s = { 0 };
//    printf("%d\n", sizeof(s));//12   0~3(1-3为浪费掉,下一个int为4)+4~7+8~11(9-11浪费掉)=12个
//    struct S2 s2 = { 0 };
//    printf("%d\n", sizeof(s2));//12  0~3(1-3为浪费掉,下一个int为4)+4~7+8~15=16个
//    struct S3 s3 = { 0 };
//    printf("%d\n", sizeof(s3));//8   
//    //0(下一个char为1,是倍数,不需要浪费)+1~4(2-4为浪费掉,下一个int为4)+5~7=8个
//    struct S4 s4 = { 0 };
//    printf("%d\n", sizeof(s4));//16   0~7+8~11(9-11为浪费掉,下一个int为4)+12~15=16个
//    struct S5 s5 = { 0 };
//    printf("%d\n", sizeof(s5));//32  
//    //0~7(1-7为浪费掉,下一个S4里面的第一个是double,为8)+8~23+23~31=32个
//    struct S6 s6 = { 0 };
//    printf("%d\n", sizeof(s6));//8
//    struct S7 s7 = { 0 };
//    printf("%d\n", sizeof(s7));//8,放在前放在后都一样
//    return 0;
//}
//为什么存在内存对齐?
// 拿空间换时间
//1.平台问题:某些平台只能在某些地址访问特定类型的数据
//2.性能原因:访问未对齐的内存,需要访问两次,对其的内存,访问一次就可以
    //所以
//在设计结构体时,既要满足对齐,又要满足空间,需要:
//让空间小的尽量集中在一起
//当对齐方式不合适时,可以自己更改默认对齐数
//修改默认对齐数方法如下
//#pragma pack()
//#pragma pack(2)
//struct S
//{
//    char c1;
//    int i;
//    char c2;
//};
//#pragma pack(1)
//struct S2
//{
//    char c1;
//    int i;
//    char c2;
//};
//int main()
//{
//    printf("%d\n", sizeof(struct S));//8   2+4+2
//    printf("%d\n", sizeof(struct S2));//6  1+4+1
//    return 0;
//}


相关文章
|
机器学习/深度学习 并行计算 Shell
docker 获取Nvidia 镜像 | cuda |cudnn
本文分享如何使用docker获取Nvidia 镜像,包括cuda10、cuda11等不同版本,cudnn7、cudnn8等,快速搭建深度学习环境。
6957 0
|
Java API
JDK API文档中文版(1.6、1.8、1.9)(附百度网盘下载地址)
JDK API文档中文版(1.6、1.8、1.9)(附百度网盘下载地址)
6706 3
JDK API文档中文版(1.6、1.8、1.9)(附百度网盘下载地址)
Cadence仿真出现Cannot Initialize Profile错误的解决方法和步骤
元器件和器件PSpice模型都准备好了,仿真原理图也画好了,但是在新建仿真配置文件的时候,提示Cannot Initialize Profile的错误。当时忘了截图了,问题解决了也没有出现这个错误。重启软件、重启电脑都没有再出现。
948 0
|
7月前
|
监控 Ubuntu Linux
ubuntu中设置开机自动运行的(sudo)指令
通过合理选择和配置上述方法,您可以确保在系统启动时自动执行所需的命令,并具备sudo权限,从而提高系统自动化管理的能力。
926 8
编译原理----0型,1型,2型,3型文法
编译原理----0型,1型,2型,3型文法
423 1
java生成word(使用Poi-tl)
java生成word(使用Poi-tl)
882 0
|
12月前
|
机器学习/深度学习 数据可视化
KAN干翻MLP,开创神经网络新范式!一个数十年前数学定理,竟被MIT华人学者复活了
【10月更文挑战第12天】MIT华人学者提出了一种基于Kolmogorov-Arnold表示定理的新型神经网络——KAN。与传统MLP不同,KAN将可学习的激活函数放在权重上,使其在表达能力、准确性、可解释性和收敛速度方面表现出显著优势,尤其在处理高维数据时效果更佳。然而,KAN的复杂性也可能带来部署和维护的挑战。论文地址:https://arxiv.org/pdf/2404.19756
220 1
|
移动开发 JavaScript 前端开发
HTML5 Audio(音频)详解
HTML5 通过 `&lt;audio&gt;` 标签简化了网页音频嵌入。本文详细介绍其基本语法与常用属性(如 `controls`、`autoplay`),并通过示例代码展示如何使用 JavaScript 控制音频播放及处理音频事件。此外,还提供了关于浏览器兼容性、自适应设计及无障碍访问的注意事项,助您优化音频体验。
|
SQL 关系型数据库 MySQL
"告别蜗牛速度!解锁批量插入数据新姿势,15秒狂插35万条,数据库优化就该这么玩!"
【8月更文挑战第11天】在数据密集型应用中,高效的批量插入是性能优化的关键。传统单条记录插入方式在网络开销、数据库I/O及事务处理上存在明显瓶颈。批量插入则通过减少网络请求次数和数据库I/O操作,显著提升效率。以Python+pymysql为例,通过`executemany`方法,可实现在15秒内将35万条数据快速入库,相较于传统方法,性能提升显著,是处理大规模数据的理想选择。
598 5
|
网络协议 Linux 网络安全
Iptables 命令完整指南
【8月更文挑战第20天】
4119 0
Iptables 命令完整指南