您现在的位置是:亿华云 > IT科技类资讯

三种管理 C 程序中标志位的方法,最后一种比较秀

亿华云2025-10-04 00:46:43【IT科技类资讯】3人已围观

简介正文在嵌入式开发中难免会涉及到非常多的标志位处理,特别是玩单片机、裸机开发的朋友,比如跟一些模块配合联调会遇到各种信号是否到位、成功等等状态,而这些信号大多都是bool类型,1个bit即可进行标识。

正文

在嵌入式开发中难免会涉及到非常多的种管中标志位标志位处理,特别是程序玩单片机、裸机开发的法最朋友,比如跟一些模块配合联调会遇到各种信号是后种否到位、成功等等状态,比较而这些信号大多都是种管中标志位bool类型,1个bit即可进行标识。程序

当然如果仅仅是法最几个标志,直接拿个uint8_t的后种整形来进行标识也不会影响什么,但如果特别多的比较话似乎就比较废RAM了。

然而为了更好的种管中标志位管理这些标志位等,有个如下几种方式供大家更好的程序管理这些标志位 :

1.位域直接标识

采用位域是管理这些标志位比较直接且方便的方式,代码如下所示:

这些标志位的法最操作无非就是置位,清零、后种以及读取三种方式。比较

1typedef union _tag_SystemFlag

2{

3 uint16_t all;

4 struct

5 {

6 uint16_t Run :1;

7 uint16_t Alarm :1;

8 uint16_t Online :1;

9 uint16_t TimerOver :1;

10 uint16_t Reserver :12;

11 }bit;

12

13} uSystemFlag;

14

15uSystemFlag unSystemFlag;16

17int main(int argc, char *argv[]) {

18

19 unSystemFlag.all = 0x00; //系统标志清除

20

21 unSystemFlag.bit.Run = 1; //置位

22 unSystemFlag.bit.Alarm = 1;

23 unSystemFlag.bit.Online = 1;

24 unSystemFlag.bit.TimerOver = 1;

25

26 unSystemFlag.bit.Run = 0; //清零

27 unSystemFlag.bit.Alarm = 0;

28 unSystemFlag.bit.Online = 0;

29 unSystemFlag.bit.TimerOver = 0;

30

31 return 0;

32}

但如代码中这样的香港云服务器操作方式在语句或语义表达上还是不够直观。

bug菌经常谈到,代码可以不写注释,不过你的每个变量、函数名称等需要足够的直观,所以很多朋友习惯把这些标志封装起来。

2.枚举+移位

为了更好的表达一般会对标志位进行进一步的封装,如下代码所示:

当然封装成函数是相对比较耗时的,不过代码也会更加的易懂,如果确实容忍不了函数封装带来的时间消耗,把函数修改为宏代码片段或者内敛函数(当然前提是编译器支持)也是可行的。

1typedef enum _tag_Flag {

2cEmRun = 0,

3cEmAlarm,

4cEmOnline,

5cEmTimerOver

6}emSystemFlag;

7

8uint16_t SystemFlag ;

9//置位

10void SetFlag(emSystemFlag flag)

11{

12 SystemFlag |= ((uint16_t)0x01) << flag;

13}

14//清除

15void ClrFlag(emSystemFlag flag)

16{

17 SystemFlag &= ~(((uint16_t)0x01) << flag);

18}

19//获得状态

20uint8_t GetFlag(emSystemFlag flag)

21{

22 return (((SystemFlag & (((uint16_t)0x01) << flag)) != 0)? true:false);

23}

24

25int main(int argc, char *argv[]) {

26

27 SetFlag(cEmAlarm);

28

29 if(GetFlag(cEmAlarm) == true)

30 {

31 printf("ClrFlag\r\n");

32 ClrFlag(cEmAlarm);

33 }

34 else

35 {

36 printf("SetFlag\r\n");

37 SetFlag(cEmAlarm);

38 }

39 return 0;

40}

3.宏列表

或许这里才是本文的重中之重~

以前跟大家介绍过,用宏自动化的生成各种代码片段,以使得代码更加的云南idc服务商紧凑。当然可读性会相对降低一点,但对于重复性代码就不需要太多考虑了。

如果以前有过类似代码处理的朋友,应该看这段代码还是比较轻松的吧,如果有点生疏,可以一层一层展开了解。

1#include

2#include

3

4typedef unsigned char uint8_t;

5typedef unsigned int uint16_t;

6typedef signed char int8_t;

7typedef int int16_t;

8

9#define true 1

10#define false 0

11

12

13//宏列表

14#define TAG_LIST(tag) \

15tag(Run)\

16tag(Alarm)\

17tag(Online)\

18tag(TimerOver)

19

20

21//枚举处理

22#define DEFINE_TAG(_tag) _tag,

23enum Flag {

24None = 0,

25TAG_LIST(DEFINE_TAG)

26EmMAX

27};

28#undef DEFINE_TAG

29

30//位定义变量

31uint16_t SysFlag = 0x0000;

32

33

34//通用方法定义

35uint8_t GetFlags(uint16_t mask)

36{

37 return ((SysFlag & mask) != 0)? true:false;

38}

39

40void SetFlags(uint16_t mask)

41{

42 SysFlag |= mask;

43}

44

45void ClrFlags(uint16_t mask)

46{

47 SysFlag &= ~mask;

48}

49

50

51//自动生成三类函数定义

52#define FLAG_Operater(flag) \

53uint8_t get##flag() { \

54return GetFlags(1 << flag);\

55}\

56void set##flag() { \

57SetFlags(1 << flag);\

58}\

59void clr##flag() { \

60ClrFlags(1 << flag);\

61}

62

63//反向函数关联

64TAG_LIST(FLAG_Operater)

65

66int main(int argc, char *argv[]) {

67

68 setRun();

69 setAlarm();

70

71 if(getAlarm() == true)

72 {

73 printf("set \r\n");

74 }

75 else

76 {

77 printf("clr \r\n");

78 }

79

80 return 0;

81}

其主要的功能就是通过宏替换和代码拼接符号,自动的生成通用的代码片段,这样做的好处就是不再需要我们在代码中定义一大堆setflag、clrflag、getflag等函数。

通过上面的代码当我们向TAGLIST宏中添加一个标识符,即可生成一系列相关的操作函数等。

这样一方面可以及简化代码,同时也避免一些人工编码带来的错误。

云服务器

很赞哦!(31)