当前位置: 首页 > article >正文

【C语言】自定义类型:结构体(下)

 

本篇博客将继续讲解结构体:

1、结构体传参

2、结构体实现位段

1、结构体传参

552a4f88461946ec9f93a6c519edc4b2.png

代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
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);//传地址
}

上面的print1和print2函数哪个好呢?首选print2函数

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

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

结论:结构体传参的时候,要传结构体的地址。

 

2、结构体实现位段

(1)什么是位段

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

1))位段的成员必须是int    ,  unsigned   int  或signed  int   ,在C99中,位段成员的类型也可以是其他的类型。

2))位段的成员名后边有一个冒号和一个数字。

例如:

struct  A
{
    int _a : 2;//_a只占2个bit位
    int _b : 5;//_b只占5个bit位
    int _c : 10;//_c只占10bit位
};

A就是一个位段类型。

位段是专门用来节省内存的。

例如:

1137c85db49a49b6af85673c97c16b89.png

 

 

c6ddd8a3e07342f2bffdc8f6f012d37e.png

 

(2)位段的内存分配

1))位段的成员可以是int ,     unsigned  int  ,   signed   int   ,  或者是  char  等类型

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

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

比如:

1:申请到的一块内存中,从左向右使用,还是从右向左使用,是不确定的。在vs中是从右向左使用的。

2:申请到的一块内存,使用后剩余的空间,不足下一个成员使用的时候,是浪费呢?还是继续使用?vs中是浪费掉。

 

例如:

af17c24265b44535a959ac3b3b159a55.png

 

 

例子讲解:

f8083acc4ce54f96b8a19fc110be6422.png

 

又因为a有3个bit位,所以存储a时只存储010,b有4个bit位,所以存储b时只存储1100,c有5个bit位,所以存储c时只存储00011,d有4个bit位,所以存储d时,只存储0100

在内存中的存储:

7713b0de4734467388808ff066403ab9.png

 

(3)位段的跨平台问题

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

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

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

4))当一个结构体包含两个位段,第二个位段成员比较大,无法容纳第一个位段剩余的位时,是舍弃剩余的位,还是利用,这是不确定的。

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

 

 

 


http://www.kler.cn/news/364945.html

相关文章:

  • Android 判断手机放置的方向
  • 程序结束、脚本语言、LISP、Python
  • Python中input()输入函数和print()输出函数的用法
  • qt QLineEdit详解
  • C语言_通讯录_进阶
  • 探索 JavaScript 事件机制(四):React 合成事件系统
  • 《首尔破笑组:在欢笑中触摸生活的温度》
  • 给已经写好的裸机程序移植freeRTOS操作系统(二)
  • 6.Three.js贴图与uv映射(uv坐标)理解和实践
  • 鸿蒙应用示例:仿钉钉日历新建日程
  • C语言中的分支与循环(中 1)
  • Java中的基本数据类型和引用类型存储在JVM中那个区域?
  • 缓存池(对象池)使用
  • 现代山东比较出名的人物颜廷利:以塑造智慧为荣,以失去素质为耻
  • MATLAB Simulink (一)直接序列扩频通信系统
  • 深入理解 RabbitMQ 及在.NET 中的应用
  • 碰一碰发视频源码开发,矩阵短视频新模式,支持OEM
  • Python基础知识-模块与包篇
  • H7-TOOL的LUA小程序教程第15期:电压,电流,NTC热敏电阻以及4-20mA输入(2024-10-21,已经发布)
  • 【Linux】命令行参数环境变量
  • vue 对象拷贝,解决引用赋值内容变化会修改原对象的方式
  • 【K8S】快速入门Kubernetes
  • Lua 语言中的注释详解
  • 本地原生多IPseo建站
  • 阿里云的 ALB (Application Load Balancer) 然后到 nginx 和具体服务时,如果超过 60 秒请求失败
  • 【真题笔记】09-12年系统架构设计师要点总结