maqianqu 发表于 2025-4-25 17:00

写单片机的C语言结构体

1、为什么需要结构体
这里先不说什么是结构体,说说为什么需要结构体?只有知道为什么需要,才能按照你的需要去学习,这样效率才会高。你才知道在什么情况下我们需要写一个结构体,怎么样去用结构体。

这里我们以一个智能家居的项目为例。

先来看一个实际的问题

话说有一个项目上有4个传感器:光照传感器、烟雾传感器、酒精传感器、湿度传感器。然后这四个各个传感器还有设置报警的阈值范围。

一般都是这样写
#include "sys.h"
#include "delay.h"
#include "usart.h"

/*记录传感器的数值*/
float temperature; //温度
charhumidity;//湿度
charalcohol;//酒精浓度
int   illumination; //光照强度

/*记录传感器高低阈值*/
float temperature_threshold;
float humidity_threshold;
float alcohol_threshold;
float illumination_threshold;

int main(void)
{
uart_init(115200);//串口初始化
delay_init();
while(1)
{
}
}

当然你做一个项目肯定还定义了很多其他的变量,还需要记录其它变量

然后过了几天又增加了个一氧化碳传感器

然后过了几天,每个传感器还需要加个是否正常工作的标志位

因为项目的需要,然后又增加了4个相同的传感器:温湿度、光照强度、烟雾浓度、酒精浓度。

然后又增加了4个相同的传感器:温湿度、光照强度、烟雾浓度、酒精浓度。

2、结构体闪亮登场
然后搞C语言那帮家伙就造了个功能struct

1、结构体就是可以把变量包含到里面的东西

struct就代表要定义一个结构体,sensors是这个结构体的名字, 然后是一个大括号 { }

大括号里面就随意定义变量啦~

怎么使用里面的变量呢?

注意结构体是一个数据类型就像是int和char一样的这种类型

既然是一种数据类型, 那么就可以用这个数据类型定义变量

定义一个该结构体的变量

为啥要那样子定义啊?

答:你去问造C语言的那帮家伙去!问问他们为啥要设计成这样子!

然后操作结构体变量里面的成员变量。当我们定义好结构体变量后,在初始化变量里面的成员变量时就会自动出现结构体里面的成员变量,如果这个代码是你一个一个敲出来的话,你就会感叹结构体在单片机中是那么的奇妙!

有人会问为啥是结构体变量中间加个点?

答:你去问造C语言的那帮家伙去!问问他们为啥要设计成这样子。

2、其实定义结构体变量可以下面这样子

也可以定义多个

发现了没,每个结构体变量都是单独拥有结构体里面的全部成员变量。

就像是最开始说的,如果再增加一套传感器:温湿度、光照强度、烟雾浓度、酒精浓度。

使用结构体的话只需要再定义一个结构体变量即可。

但是很多时候我们在单片机中见到的结构体并不是上面那样定义的,而是在前面加了一个typedef 关键字。

这样的例子在库函数的头文件中我们经常会看到如下结构体

3、typedef关键字
先看一下百度百科对typedef的定义

总结一句就是:typedef可以把一个数据类型取一个别的名字

typedef {数据类型}{别的名字}
#include "sys.h"
#include "delay.h"
#include "usart.h"

typedef int zhjiguoxin;//zhjiguoxin就是int

zhjiguoxin value = 0;

int main(void)
{
uart_init(115200);//串口初始化
delay_init();

printf("value=%d\r\n",value);

```
while(1)
```

{
}
}

虽然typedef可以给变量取别名,但是没有谁会像上面那样取名字,我这里只是举一个例子。

4、结构体的精髓
注意下:

1、下面的代表了这个结构体数据类型

2、给这个数据类型起一个别名

注意是三部分,typedef{数据类型}{别的名字}。所以sensor就代表了这个结构体了。

建议初学者把下面这张图保存到你的电脑,这样你就***也不会忘记typedef在结构体中的用法了,也能很快的记住结构体这个东东。

3、以后定义结构体变量的时候就不需要像最开始那样struct sensors sen;这样的定义结构体变量了,只需要sensor sen;即可。

4、结构体名字可以省略

注意结构体定义可以不写结构体名,对C语言来说,那个sensors不叫结构体名,而是叫标签(tag)。C语言结构体名是struct关键字 + tag。所以为了简便我们看到的单片机中的结构体都是写成如下的形式。

5、结构体的变量可以放任何变量
1、结构体变量可以放任何变量(int型指针)
#include "sys.h"
#include "delay.h"
#include "usart.h"
typedef struct
{
float temperature; //温度
charhumidity;    //湿度
charalcohol;    //酒精浓度
int   illumination;//光照强度
charCO;//一氧化碳浓度
int   *p;//int型的指针变量
} sensor;
sensor sen;
int value =0;
int main(void)
{
uart_init(115200);//串口初始化
delay_init();
sen.p=&value;//把value的地址赋值
//打印p代表的地址里面的值(其实就是打印value的值)
printf("value=%d\r\n",*(sen.p));
while(1)
{
}
}
既然是指针变量,所以给指针变量赋值时当然是赋值的是一个地址。

2、结构体变量可以放任何变量(函数指针)
#include "sys.h"
#include "delay.h"
#include "usart.h"
typedef struct
{
float temperature; //温度
charhumidity;    //湿度
charalcohol;    //酒精浓度
int   illumination;//光照强度
charCO;//一氧化碳浓度
int   *p;//int型的指针变量
void (*fun)();
} sensor;
sensor sen;
void function()
{
printf("zhiguoxin\r\n");
}
int value =0;
int main(void)
{
uart_init(115200);//串口初始化
delay_init();
sen.fun=function;
sen.fun();
while(1)
{
}
}
既然是函数指针变量,所以给函数指针变量赋值时当然是赋值的也是地址,并且还要是一个函数的地址,而一个函数的函数名就是该函数的地址。所以才会有下面的把函数function();的地址function赋值给函数指针fun。这样大家是不是很清楚了。如果不清楚建议看个3遍以上!

3、结构体变量可以放任何变量(结构体变量)

这就是结构体嵌套,在一个结构体内包含了另一个结构体作为其成员。当出现结构体嵌套时,必须以级联方式访问结构体成员,即通过成员选择运算符逐级找到最底层的成员时再引用。
#include "sys.h"
#include "delay.h"
#include "usart.h"

typedef struct
{
int i;
}zhiguoxin;

typedef struct
{
float temperature; //温度
charhumidity;    //湿度
charalcohol;    //酒精浓度
int   illumination;//光照强度
charCO;//一氧化碳浓度
int   *p;//int型的指针变量
void (*fun)();
zhiguoxin guougo;
}sensor;

sensor sen;

int main(void)
{
uart_init(115200);//串口初始化
delay_init();

sen.guougo.i=100;
printf("i=%d\r\n",sen.guougo.i);

```
while(1)
```

{
}
}

4、结构体变量可以放任何变量(结构体指针)

结构体是一个数据类型。数据类型当然也可以定义对应的指针变量啦。

就像是int 类型可以定义 int *p; 一样

所以当大家如果发现你的代码中结构体是通过—>访问的话,那么这个结构体变量一定是指针类型的变量。同理如果代码中结构体是通过.访问的话,那么这个结构体变量就不是指针变量,而是一般的变量。

总结:到这里结构体在单片机中的应用你已经掌握的差不多了,大家可能感觉本期讲的内容太简单了,不过只有你把这个简单的基础性知识打牢,你就会进步的更快。否则你总感觉你的代码差点意思。

hudi008 发表于 2025-5-3 22:13

写单片机的C语言结构体,需要注意什么

houjiakai 发表于 2025-5-3 23:00

将常用或重要的成员放在前面,可以提高代码的可读性和访问效率。

jonas222 发表于 2025-5-4 00:35

态内存分配要谨慎使用,因为单片机的内存资源有限,动态内存分配可能会导致内存碎片问题

linfelix 发表于 2025-5-4 20:31

未初始化的结构体成员可能包含随机值。

mollylawrence 发表于 2025-5-6 09:07

位域的存储顺序和跨平台兼容性不确定。

wangdezhi 发表于 2025-5-6 10:50

单片机结构体的核心在于高效组织数据和优化内存使用。

jackcat 发表于 2025-5-6 12:35

编译器默认会对结构体成员进行内存对齐(Padding),以提高访问速度。这可能导致结构体大小超出预期,增加内存占用。

biechedan 发表于 2025-5-6 14:22

使用固定大小数组或动态内存分配            

qiufengsd 发表于 2025-5-6 16:17

结构体成员应根据实际需求进行设计,将相关的数据放在一个结构体中。成员的类型要选择合适,以节省内存空间。

mickit 发表于 2025-5-6 18:10

结构体变量可以在声明时进行初始化,也可以在后续代码中逐个成员进行赋值。初始化时要确保成员的值符合其数据类型和实际意义。

benjaminka 发表于 2025-5-6 19:54

在设计一个表示传感器数据的结构体时,要根据传感器的精度和范围选择合适的数据类型来存储数据。

modesty3jonah 发表于 2025-5-6 21:36

在结构体定义和成员变量处添加注释,说明其用途和约束。

modesty3jonah 发表于 2025-5-11 10:26

在全局/静态结构体中,可初始化成员;局部结构体需手动初始化。

bestwell 发表于 2025-5-11 12:22

在定义结构体变量时,显式初始化所有成员,避免未初始化的变量导致的不确定行为。

belindagraham 发表于 2025-5-13 16:26

传递结构体指针而非结构体本身,减少栈开销

janewood 发表于 2025-5-13 18:43

在使用结构体数组时,要确保有足够的内存空间来存储数组元素。同时,要注意数组的越界访问问题,避免因越界访问导致程序崩溃或数据错误。

lihuami 发表于 2025-5-13 20:26

简化结构体设计,去除无用字段。            

mikewalpole 发表于 2025-5-14 21:41

结构体作为函数返回值时,同样要考虑内存使用和效率问题。如果结构体较大,建议返回结构体指针,避免返回值复制带来的开销。

lidi911 发表于 2025-5-15 07:46

结构体方便程序组织和代码易读性
页: [1] 2 3 4
查看完整版本: 写单片机的C语言结构体