C语言之自定义类型_结构体篇(2)

简介: C语言之自定义类型_结构体篇(2)

今天接着我们继续自定义类型结构体。🙂🙂

结构体传参

在我们初阶结构体我们学习过结构体传参的知识。

关于下面代码:

#include<stdio.h>
struct S
{
  int data[1000];
  int num;
};
//结构体传参
//栈区形参开辟一块空间,实参开辟一块空间,很浪费
void print1(struct S s)//形参
{
  printf("%d\n", s.num);
}
//结构体地址传参
//压栈的时候只用开辟四个字节的空间,效率更高
void print2(const struct S* ps)//不安全 -> const 安全
{
  printf("%d\n", ps->num);
}
int main()
{
  struct S s = { {1,2,3,4}, 1000 };//实参
  print1(s); //传结构体 传值调用
  print2(&s); //传地址 传址调用
  return 0;
}

上面的print1和print2那个好?明显,print2。


  • 函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。
  • 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。
  • 如果觉得指针不安全,怕改变原数据,请加上const。
  • 结构体传参数的时候,要传结构体的地址。(选传址调用)

结构体实现位段(位段的填充&可移植性)

在上一篇博文我们讲完了结构,这篇我们来谈谈位段。结构会为了效率浪费空间,位段出现就是为了节省空间。

什么是位段

位段的声明和结构是类似的,有两个不同:

  • 位段的成员必须是intunsigned int signed int
  • C99之后,也可以是其他类型,但是基本上都是 intchar 整型家族🆗
  • 位段的成员名后边右一个冒号和一个数字。
//位段
struct A
{
  int _a : 2;
  int _b : 5;
  int _c : 10;
  int _d : 30;
};
//结构
struct A
{
  int _a;
  int _b;
  int _c;
  int _d;
};

  • A就是一个位段类型_位指的是二进制位
  • _a占用2个比特位
  • _b占用5个比特位
  • _c占用10个比特位
  • _d占用30个比特位

一个结构体的某一些成员,它对内存的需求,只是占了给它分配内存空间的一部分吗,用不完。那么此刻我们就可以使用位段,去保证效率的同时节省空间。


位段的大小计算

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

是否和你预期的一样呢??

  • 位段的内存分配
  • 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型。
  • 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
  • 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

不确定因素:位段的跨平台问题。

到底是怎么开辟的呢?简单来说,就是依次开辟。例如先开辟一个字节空间(8个比特位),不够的话再开辟1个字节的空间,依次下去...

那不同编译器有所差别,又有很多不确定因素。即便这样,我们还是可以探究一下在VS上到底是怎么使用的?

//一个例子
struct S
{
char a:3;
char b:4;
char c:5;
char d:4;
};
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
//空间是如何开辟的?

我们猜测在VS编译器上:

  • 内存分配是从低地址到高地址
  • 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的。


我们验证发现,果然等于3。

有人说可能是巧合,或者从高到低地址也是这样的。那我们调试验证一下。

调试,&s之后,在内存窗口。

位段的跨平台问题


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

位段的应用

位段应用在网络工程等方面。有兴趣可以下去了解一下

✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!

代码------→【gitee:唐棣棣 (TSQXG) - Gitee.com

联系------→【邮箱:2784139418@qq.com】

目录
相关文章
|
24天前
|
存储 C语言
C语言程序设计核心详解 第九章 结构体与链表概要详解
本文档详细介绍了C语言中的结构体与链表。首先,讲解了结构体的定义、初始化及使用方法,并演示了如何通过不同方式定义结构体变量。接着,介绍了指向结构体的指针及其应用,包括结构体变量和结构体数组的指针操作。随后,概述了链表的概念与定义,解释了链表的基本操作如动态分配、插入和删除。最后,简述了共用体类型及其变量定义与引用方法。通过本文档,读者可以全面了解结构体与链表的基础知识及实际应用技巧。
|
1月前
|
C语言
c语言中的结构体
本文档详细介绍了C语言中结构体的使用方法,包括结构体的基本定义、变量声明与赋值、数组与指针的应用,以及结构体嵌套、与`typedef`结合使用等内容。通过示例代码展示了如何操作结构体成员,并解释了内存对齐的概念。
|
2月前
|
C语言
C语言结构体赋值的四种方式
本文总结了C语言结构体的四种赋值方式,并通过示例代码和编译运行结果展示了每种方式的特点和效果。
56 6
|
2月前
|
编译器 程序员 Linux
【C语言篇】结构体和位段详细介绍
跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。
|
2月前
|
存储 编译器 C语言
【C语言篇】自定义类型:联合体和枚举详细介绍
像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。
|
2月前
|
存储 安全 编译器
C语言自定义类型
C语言自定义类型
29 10
|
2月前
|
存储 C语言
C语言------结构体和共用体
这篇文章是关于C语言中结构体和共用体的实训,通过示例代码演示了结构体的定义、赋值、使用,以及如何使用结构体变量进行数据的组织和操作,包括输入、排序、求平均分和查找学生信息等功能。
C语言------结构体和共用体
|
4月前
|
网络协议 编译器 Linux
结构体(C语言)
结构体(C语言)
|
3月前
|
存储 编译器 定位技术
结构体数组在C语言中的应用与优化策略
结构体数组在C语言中的应用与优化策略
|
3月前
|
存储 编译器 数据库
结构体数组在C语言中的应用与优化技巧
结构体数组在C语言中的应用与优化技巧