结构体全解,适合初学者的一条龙深度讲解(附手绘图详解)下

简介: 结构体全解,适合初学者的一条龙深度讲解(附手绘图详解)

2.1修改默认对齐数


我们可以通过#pragma pack()指令来修改默认对齐数。


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


968045478fc11a763247b86708e8801d_01ec18b9e3da48b8a60163a9b0185089.png


可以看到,答案不再是12,默认对齐数确实被修改了。


想要取消的话就引入一个空指令。


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


a4973c80bc93d1b85c6291017aca52bb_dcdae90c9721485bba16108f55ea6530.png


2.2 结构体传参


下面print1和print2那个比较好?


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

上面的 print1 和 print2 函数哪个好些?

答案是:首选print2函数。

原因:

函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。

如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。

所以结构体传参数时,要传结构体的地址。


3.1位段


结构体讲完就得讲讲结构体实现 位段 的能力。

struct A
{
 int _a:2;
 int _b:5;
 int _c:10;
 int _d:30;
};

A就是一个位段的类型,位段可以控制所给的空间大小,达到节省空间的目的。


它所占空间是多大?


#include <stdio.h>
struct A
{
  int _a : 2;
  int _b : 5;
  int _c : 10;
  int _d : 30;
};
int main()
{
  printf("%d\n", sizeof(struct A));
  return 0;
}


e567e08aa3df4cd5a68b1cfeb9cd141b_144a3809ce294084ad85275b813a0dd4.png


它占了8*8=64个比特位。


从16个字节优化到8个字节,位段的功能可以说是十分强大。


3.2 位段的内存分配


1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型

2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。

3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

#include <stdio.h>
//一个例子
struct S
{
  char a : 3;
  char b : 4;
  char c : 5;
  char d : 4;
};
int main()
{
struct S s = { 0 };
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
//空间是如何开辟的?
return 0;
}


首先做一个假设,假设内存中的比特位是由右向左使用的。

一个字节内部,剩余的比特位不够使用时,直接浪费掉。


14da58387aaba67e5f185188dfd193ba_8b4225b5319f474b8412cefbff62afa3.png


我们猜想是这个样子。


转换成16进制为:


62  03  04


我们来调试看看:


2f717c4b63d0f72f57b1bfa54d44a952_362b666259d04c64be1e470baf7d2359.png


我们的猜想是正确的!


3.3 位段的跨平台问题


1. int 位段被当成有符号数还是无符号数是不确定的。

2. 位段中最大位的数目不能确定。( 16 位机器最大 16 , 32 位机器最大 32 ,写成 27 ,在 16 位机

器会出问题。

3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。

4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是

舍弃剩余的位还是利用,这是不确定的。

总结:

跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在。


5afd1174262572c8492490f4c580e7b1_304e31657dd24eee9c48b710a07b8d3e.png


这篇博客旨在总结我自己阶段性的学习,要是能帮助到大家,那可真是三生有幸!😀如果觉得我写的不错的话还请点个赞和关注哦~我会持续输出编程的知识的!🌞🌞🌞  


相关文章
|
2月前
|
存储 缓存 安全
C++数组全解析:从基础知识到高级应用,领略数组的魅力与技巧
C++数组全解析:从基础知识到高级应用,领略数组的魅力与技巧
54 1
|
1月前
原型制作与图解——墨刀工具
原型制作与图解——墨刀工具
原型制作与图解——墨刀工具
|
5月前
第七章:函数实训
第七章:函数实训
17 0
|
10月前
|
存储 编译器 C语言
结构体全解,适合初学者的一条龙深度讲解(附手绘图详解)上
结构体全解,适合初学者的一条龙深度讲解(附手绘图详解)
61 0
|
SQL 开发框架 小程序
小程序开发-第二章第一节小程序的模板-评分星星模板-全栈工程师之路-中级篇
小程序开发-第二章第一节小程序的模板-评分星星模板-全栈工程师之路-中级篇
120 0
小程序开发-第二章第一节小程序的模板-评分星星模板-全栈工程师之路-中级篇
|
JavaScript 算法 程序员
推荐一个采用方便程序员在线动画学习常用算法的良心网站
网址:https://algorithm-visualizer.org/ 进去之后的页面是程序员熟悉的码农风格: 假设我想学习冒泡排序算法,在搜索栏里输入sort,在结果列表里选择bubble sort: 点击之后,排序操作处于就绪状态,点击play开始: 此时右边的JavaScript代码像我们平时单步调试一样逐行执行,同时每一步执行后排序的效果在屏幕正中实时显示: 比单步调试更强大之处是,我们能随时回退到前面的执行结果,通过下图高亮的84/144这个柱状开关控制。
1538 0