目录

一、结构体类型的声明

二、结构体的自引用

三、结构体变量的定义和初始化

1、结构体变量的定义

2、结构体变量的初始化

四、结构体内存对齐

五、修改对齐数

六、结构体传参


一、结构体类型的声明

struct stu
{char arr[20];int age;int hight;
}s1;

其中struct——结构体关键字,stu——结构体标签,是根据自己的需求写,这里我举例为学生,大括号里面的是结构体成员变量,s1——结构体变量,这里注意,虽然在创建结构体的时候,加了大括号后末尾会自动分号“;”,但是还是不要忘记不能丢。

结构体还可以匿名声明,就是不写结构体标签:

struct
{char arr[20];int age;int hight;
}s1;

这种结构体变量也能用,不过只能在大括号后面和分号中间创建变量,在其他地方都不能创建变量,

另外,如果再创建一个一样的结构体,成员变量也一模一样的结构体指针p,是不能取地址s1赋值给p的,因为编译器会认为它们两个是不同的结构体类型。


二、结构体的自引用

结构体是可以包含一个结构体的,但是这个被包含的结构体的大小必须是确定了的,否则这个大的结构体大小也无法确定。

struct Node
{int data;struct Node next;
};

像这样结构体中包含自己,那就是无法算出它的大小,如果想包含,就在成员变量里的结构体加一个“*”,表示是一个指针,大小就是4个字节:

struct Node
{int data;struct Node* next;
};

三、结构体变量的定义和初始化

1、结构体变量的定义

struct stu
{char arr[20];int age;int hight;
}s1 = { "王五",19,183 };struct stu s2 = { "李四",18,175 };int main()
{struct stu s3 = { .arr = "张三",.age = 18,.hight = 180 };struct stu s2 = { .age = 19,.hight = 183,.arr = "王五" };printf("姓名:%s  年龄:%d  身高:%d\n", s1.arr, s1.age, s1.hight);printf("姓名:%s  年龄:%d  身高:%d\n", s2.arr, s2.age, s2.hight);printf("姓名:%s  年龄:%d  身高:%d\n", s3.arr, s3.age, s3.hight);return 0;
}

我们有三种定义方式:

1、在创建结构体的时候一起创建了结构体变量,例如s1,

2、在main函数外部创建结构体变量,例如s2,

3、在main内部创建的变量,例如s3,

其中s1和s2是全局变量,s3是局部变量。

2、结构体变量的初始化

可以在创建变量的同时一起初始化,也可以在函数内部进行初始化,在函数内部初始化可以打乱顺序,即在括号内指定成员变量进行初始化。


四、结构体内存对齐

我们知道char占1个字节,short占2个字节,int占4个字节,float占4个字节,long占8个字节,double占8个字节,那么一个结构体大小是几呢?

计算方法如下:

1、第一个成员在与结构体变量偏移量为0的地址处。

2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处,在vs中默认对齐数是8。

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

4、如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐

数)的整数倍。

举个例子:

struct stu
{char arr;int age;int hight;
}s1;

第一个成员变量是char类型,1个字节,比默认对其数8小,所以对齐数为1,从0开始,占1个字节空间。

第二个是int类型,4个字节,默认对齐数是8,而int是4,所以对齐数是4,前面只占了一个字节的空间,不够4的倍数,所以只能浪费空间,从4开始,占4个空间(4,5,6,7),

第三个也是int类型,此时,正好是从8开始分配空间(8,9,10,11)。

从0~11,总共是12个字节,是最大对其数4的倍数,所以该结构体的大小为12。

再来一道题:

struct stu
{char arr[3];int age;int hight;
}s1;struct A
{int a;struct stu s1;
}A1;int main()
{printf("%d\n", sizeof(A1));//printf("%d\n", sizeof(s1));return 0;
}

该输出结果为16,这里要注意两个点:

第一,s1中的char类型是个数组,是占3个字节,经过计算,该结构体的大小为12,

第二、A1中包含s1结构体,算大小的时候,先给a分配4个字节空间,在看s1中的最大对齐数,是4,所以不用浪费空间,直接从4开始分配,分配空间大小就是s1的大小,,所以是4 + 12 = 16个字节。

搞这么麻烦,为什么要这样设置内存对齐呢?

1、平台原因:不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特 定类型的数据,否则抛出硬件异常。

2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内

存访问仅需要一次访问。

那么如何有效的减小空间呢?

我们可以在创建结构体变量时,把结构体成员变量的类型大小从小到大排。


五、修改对齐数

这里我们用到一个预处理指令:#pragma

#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{char c1;int i;char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
struct S2
{char c1;int i;char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
int main()
{//输出的结果是什么?printf("%d\n", sizeof(struct S1));printf("%d\n", sizeof(struct S2));return 0;
}

结构在对齐方式不合适的时候,我们可以自己更改默认对齐数。


六、结构体传参

传参和基本数据类型传参一样:

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;
}

传值,相当于是临时拷贝一份,而传址,是把地址传过去,我们优先考虑传址,因为函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销就比较大,所以会导致性能的下降。

关于结构体类型的讲解相关推荐

  1. 结构体PLUS(计算结构体类型大小及位段)~~

    如何计算结构体类型大小呢? 1. 结构体内存对齐 为什么要内存对齐呢? 2.修改默认对齐数 3.位段 什么是位段 位段的内存分配 位段的跨平台问题 位段的应用 关于结构体类型,之前阿涛写过一篇文章,里 ...

  2. 结构体类型、联合体类型

    结构体和联合体 一.结构体类型 1. 结构体类型的设计和初始化 2. 结构体大小的计算 3. 结构体成员的访问和赋值 4. 结构体类型和指针 (1)变量名为指针时: (2)结构体赋值时容易出现的问题: ...

  3. vector 结构体类型 使用 排序

    如果要在Vector容器中存放结构体类型的变量,经常见到两种存放方式. 方式一:放入这个结构体类型变量的副本. 方式二:放入指向这个结构体类型变量的指针. 假设结构体类型变量是这样的, typedef ...

  4. c语言中结构体类型只有,C语言中main()函数不要返回结构体类型(求助)

    大家先看一下这段程序: #include typedef unsigned char bool; typedef struct _person person; struct _person { boo ...

  5. c语言定义学生结构体类型,C语言中结构体的三种定义方式

    c语言中结构体的定义: struct 结构体名{ 成员列表: ..... }结构体变量: 7.1.1 结构体类型变量的定义 结构体类型变量的定义与其它类型的变量的定义是一样的,但由于结构体类型需要针对 ...

  6. (篇十)用结构体数组处理学生成绩、结构体类型函数求平均值

    文章目录 一.结构体变量 二.用结构体数组处理学生成绩 三.结构体类型函数求平均值 用C语言学好结构化编程逻辑!本篇主要分析结构体数组和结构体类型的函数,对于二级C语言来说,主要是考处理学生多个成绩上 ...

  7. 结构体类型(struct)

    一.定义结构 结构体特点: 1.结构是由不同数据类型的数据组成的集合体. 2.结构由数目固定的成员构成 3. 各成员可以具有不同的数据类型 4.一个结构变量在内存占有一片连续的存储空间 定义结构体需要 ...

  8. 关于定义结构体类型的步骤以及应注意的细节

    #include <stdio.h> #include <string.h> //关于定义结构体类型的步骤以及应注意的细节 //定义结构体变量类型 //结构体只定义不初始化,系 ...

  9. 指向结构体类型的指针

    结构体变量的指针就是该变量所占据的内存段的起始地址.可以定义一个指针变量来指向一个结构体变量,也可以动态分配内存存放结构体各成员数据. 与指向普通数据类型的指针变量相同,也可以定义指向结构体数据类型的 ...

最新文章

  1. 经典面试题:ES如何做到亿级数据查询毫秒级返回?
  2. volatile关键字对
  3. opencv 边缘检测
  4. 你必须学会的Git入门基本操作
  5. word如何设置上标形式_如何在word中设置特殊页码
  6. 看!闲鱼在ServiceMesh的探索和实践
  7. 文末送书啦!| Device Mapper,那些你不知道的Docker核心技术
  8. javascript Array学习与使用
  9. C/C++学习----第二章 继承和派生
  10. gstreamer正确的结束办法
  11. 京瓷1800打印机扫描步骤_京瓷复印机扫描设置方法京瓷复印机扫描到电脑设置...
  12. 基于AT89S52的俄罗斯方块游戏设计与实现
  13. 语音系统智能AI机器人AI源码营销机器人电销机器人智能电话机器人拨号机器人语音机器人空号识别FreeSWITCH呼叫中心中间ipbxIPBX科大识别阿里识别语音识别语音翻译
  14. Unity游戏开发客户端面经——性能优化(初级)
  15. 全自动与半自动手表的区别_机械表全自动好还是半自动好 有什么区别
  16. 一文教你看懂POS单上的商户编号
  17. Win10 英伟达显卡驱动安装不上,显示由于该设备有问题,Windows已将其停止,错误代码43
  18. Kubernetes 的 HPA 原理详解
  19. 华为鸿蒙系统学习笔记1-介绍
  20. 谷歌 Core Web Vitals:SEO页面速度优化指南

热门文章

  1. 【Linux】限制进程的CPU使用率
  2. 初学前端收集的字体图标以及字体网站
  3. 算法设计与分析第2版第一章
  4. Flutter学习记录——23.实现一个类似淘宝的商品展示页面
  5. 思科:vtp,vlan中继协议的配置方法
  6. Ruby 简单入门(一)
  7. VHDL智力竞赛抢答器设计
  8. 【产品方案】如何全面建设B端产品中的数据迁移方案
  9. 【云计算学习笔记(一)】之 虚拟化技术分类
  10. 利用aircrack-ng破解WIFI密码