深入探索C语言struct的用法

简介: 深入探索C语言struct的用法

文章开始之气那,给大家分享一个C语言在线练习的网站(本人常用):C语言在线练习


struct的作用


一般来说,区别一个开发人员是否具备丰富开发经历的标志在于其会不会使用struct,怎么使用strcut


在网络协议、通信控制、嵌入式系统的编程中,我们经常要传送的不是简单的字节流(char型数组),而是多种数据组合起来的一个整体,其表现形式是一个结构体。

初级的开发人员往往将所有需要传送的内容依顺序保存在char 型数组中,通过指针偏移的方法传送网络报文等信息。这样做编程复杂,易出错,而且一旦控制方式及通信协议有所变化,程序就要进行非常细致的修改。


一个有经验的开发者则灵活运用结构体,举一个例子,假设网络或控制协议中需要传送三种报文,其格式分别为packetA、packetB、packetC


typedef struct StructA {
  int a;
  char b;
} A;
typedef struct StructB {
  chara;
  shortb;
} B;
typedef struct StructC {
  int a;
  char b;
  float c;
} C;

报文结构设计

typedef enum PacketType{
  PacketTypeA = 1,
  PacketTypeB,
  PacketTypeC
};
struct CommuPacket {
  PacketType type;  < 报文类型
  union {          < 每次传输的是其中的一种,因此使用union
    A packet_a;
    B packet_b;
    C packet_c;
  }
};

报文传输设计

/* pSendData 发送字节流的首地址
   len 发送数据长度
*/
void Send(char *pSendData, unsigned int len);
/* pRecvData 接收缓冲区首地址
   len 接受长度 
   返回值:实际接收长度
*/
unsigned int Recv(char *pRecvData, unsigned int len);

判断报文类型,并作相应处理

switch(type) {
  case PacketTypeA :
  ...
  break;
  case PacketTypeB :
  ...
  break;
  case PacketTypeC :
  ...
  break;
}


struct成员对齐


自然对齐


struct 是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float 等)的变量,也可以是一些复合数据类型(如array、struct、union 等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。


自然对界(natural alignment)即默认对齐方式,是指按结构体的成员中size 最大的成员对齐。

struct Natural {
  char a;
  short b;
  char c;
}

在上面的这个结构体中,size最大的数据类型为short,长度为两个字节。因此,结构体中所有成员变量都以2为单位对齐。


其大小为sizeof(Natural) = 6


指定对界


一般使用预处理指令#pragma pack来改变缺省的对界条件


使用伪指令#pragma pack (n),编译器将按照n 个字节对齐

使用伪指令#pragma pack (),取消自定义字节对齐

如果#pragma pack (n)中指定的n 大于结构体中最大成员的size,则其不起作用,结构体仍然按照size 最大的成员进行对界


#pragma pack (n)
struct Natural {
  char a;
  int b;
  char c;
};
#pragma pack ()


当n 为4、8、16 时,其对齐方式均一样,sizeof(naturalalign)的结果都等于12。而当n 为2时,其发挥了作用,使得sizeof(Natural)的结果为6。


通过__attribute((aligned (n)))也可以让所作用的结构体成员对齐在n 字节边界上,但它使用较少

相关文章
|
5月前
|
C语言
C 语言中布尔值的用法和案例解析
在编程中,您经常需要一种只能有两个值的数据类型,例如: - 是/否 - 开/关 - 真/假 为此,C语言有一个 `bool` 数据类型,称为布尔值。
188 1
|
5月前
|
算法 编译器 C语言
C语言猜数字小游戏(也包含python实现的用法)
本文基于VS2022、pycharm和前面的知识,写一个凭借分支与循环的小游戏,比如: 写一个猜数字游戏 游戏要求: 电脑自动生成1~100的随机数 玩家猜数字,猜数的过程中,根据猜测数据的大小给出大了或小了的反馈,直到猜对,游戏结束 在pyhton中生成随机数是比较简单的,可以直接导入random的包,直接生成随机数,导致写猜数字小游戏变成了判读语句和循环语句嵌套就能写出来,所以我不做过多的介绍了,可以直接看后面的代码展示,想了解更多的python可看python的基础知识,这里面有我在学习python的过程中写的笔记
74 0
|
5月前
|
编译器 C语言
C语言的转义字符,转义字符的用法
C语言的转义字符,转义字符的用法
|
5月前
|
存储 C语言 索引
【c语言指针详解】复杂数据结构的指针用法
【c语言指针详解】复杂数据结构的指针用法
135 0
|
5月前
|
存储 C语言
【c语言指针详解】指针的基本概念和用法
【c语言指针详解】指针的基本概念和用法
161 0
|
1月前
|
C语言
C语言判断逻辑的高阶用法
在C语言中,高级的判断逻辑技巧能显著提升代码的可读性、灵活性和效率。本文介绍了六种常见方法:1) 函数指针,如回调机制;2) 逻辑运算符组合,实现复杂条件判断;3) 宏定义简化逻辑;4) 结构体与联合体组织复杂数据;5) 递归与分治法处理树形结构;6) 状态机管理状态转换。通过这些方法,可以更高效地管理和实现复杂的逻辑判断,使代码更加清晰易懂。
212 88
|
2月前
|
存储 缓存 编译器
【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)(下篇)
scanf处理⽤⼾输⼊的原理是,⽤⼾的输⼊先放⼊缓存,等到按下回⻋键后,按照占位符对缓存进⾏解读。 解读⽤⼾输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为⽌。
130 2
|
2月前
|
存储 C语言
【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)(上篇)
printf 的作⽤是将参数⽂本输出到屏幕。它名字⾥⾯的 f 代表 format (格式化),表⽰可以定制输出⽂本的格式。
66 1
|
4月前
|
存储 C语言
c语言scanf函数用法
c语言scanf函数用法
|
4月前
|
存储 C语言
C语言学习记录——联合体(共用体、特点、用法、联合体大小计算)
C语言学习记录——联合体(共用体、特点、用法、联合体大小计算)
70 2