C语言枚举、结构体、共用体综合应用实例

来源:互联网 发布:多益网络官网手游注册 编辑:程序博客网 时间:2024/05/16 18:26

C语言中使用用户建立数据类型时会接触结构体、共用体、枚举类型等,这些常见的类型在程序设计中实现功能常常会有很大的好处,也更能体现开发人员的专业性,也能使程序结构清晰,严谨。下面就以在嵌入式软件设计为例,根据实际问题说说枚举类型和结构体、共用体的应用。

在此之前还是先看看一下这些常见类型的使用情况。

结构体

struct 结构名

{

成员表列

}

struct {    int a;    char b;    double c;} s1;

或者

struct SIMPLE{    int a;    char b;    double c;};

共用体

union 共用体类型名

{

成员列表

}

typedef union{ char c; int a; int b;}Demo;

枚举类型

enum 枚举名{ 枚举值表 };

enum weekday{ sun,mou,tue,wed,thu,fri,sat };enum weekday a,b,c;

枚举常用switch-case开关语句联合使用。

以上为基本用法,下面介绍这些类型的实际和综合应用。

实例背景: 设计一个数据采集系统,能够对电网众多数据进行采集并通过总线(RS485)传输。

设备:数据采集芯片、CPU等

对硬件部分就不详细说明了,软件主要是对芯片驱动(包括LCD driver等),以及通信协议等。下面就介绍这些常用模块中如何使用结构体、共用体、枚举等较好实现模块功能。

先说枚举类型:

枚举主要是可以任意给枚举元素赋值

enum {  SYS_OK = 0,  SYS_COMM_ERROR,  SYS_COMM_RETRY,  SYS_COMM_WAIT,  SYS_REBOOT,  SYS_OVER_THRESHOLD,  SYS_UART_DEVICE_ID_ERROR,  SYS_DEVICE_OPEN_CIRCUIT,  SYS_DEVICE_SHORT_CIRCUIT,  SYS_DEVICE_OVER_THRESHOLD,};

以上枚举类型中可以区分不同状态,这样根据枚举元素进行索引就可以判断系统处于哪一种状态中。下面是LCD驱动的一种写法:

enum{        ComplexDigtalNumFirst_I       =  0,        ComplexDigtalNumFirst_F       =  0,        ComplexDigtalNumFirst_G       =  0,        ComplexDigtalNumFirst_M       =  0,        ComplexDigtalNumFirst_N       =  1,        ComplexDigtalNumFirst_E       =  1,        ComplexDigtalNumFirst_A       =  2,        ComplexDigtalNumFirst_J       =  2,        ComplexDigtalNumFirst_K       =  2,        ComplexDigtalNumFirst_B       =  2,        ComplexDigtalNumFirst_L       =  3,        ComplexDigtalNumFirst_C       =  3,        ComplexDigtalNumFirst_D       =  3,}

以上代码片段可以表示地址,也可以表示其他的含义,其实说简单点枚举类型就是功能划分比较清楚一点,还有就是写出来的程序比较规范一些,关键还是对数字的索引,但是每一个数字可以表示不同的含义,数字可以相同,使用起来比较灵活,在于使用者如何进行功能划分了。

结构体的使用

先看看STM32库函数中关于结构体的使用:

typedef struct { vu32 CRL; vu32 CRH; vu32 IDR; vu32 ODR; vu32 BSRR; vu32 BRR; vu32 LCKR; } GPIO_TypeDef; typedef struct { vu32 EVCR; vu32 MAPR; vu32 EXTICR[4]; } AFIO_TypeDef;

在数据通信时,如果数据较多我们可以将很多数据打包发送,这时候结构体使用起来是很方便的:

typedef struct {              short year;    unsigned char month;    unsigned char day;    unsigned char hour;    unsigned char minute;}Date_S;typedef struct {    int A_I;    int B_I;    int C_I;    int N_I;    int A_DMD;    int B_DMD;    int C_DMD;    int N_DMD;    int A_PECK;    int B_PECK;    int C_PECK;    int N_PECK;    Date_S A_PEAK_TIME;    Date_S B_PEAK_TIME;    Date_S C_PEAK_TIME;    Date_S N_PEAK_TIME;    int I_UNBAL;    int U_A_B;    int U_B_C;      int U_A_C;    int UNBAL_ABC;    int U_A_N;    int U_B_N;    int U_C_N;    int UNBA_ABCN;    int PQS_KW;    int PQS_KVAR;    int PQS_KVA;    }

这样对于数据发送检验以及接收后拆包进行数据处理都挺方便,特别是使用结构指针时更灵活了。使用C语言写实际应用程序时,结构体的使用特别多,不管是游戏还是一些实用程序里面,包括linux底层(用C来写),因为结构体里面可以是结构体、共用体等其他的类型,下面就给出了一个实际应用中结构体与共用体联合使用的实例:

union Package{    struct Packet_base package_base;    struct PACKDATA_Energy package_energy;};struct Frame{    unsigned char head;// = 0x5A;    unsigned char cmd;// = 0x64;    unsigned char len; //= 5;    union Package package;    unsigned char seq; //= 0;    unsigned short check;    unsigned char tail;// = 0xF0;};

上面代码段是一段RS485通信进行数据传输的主要实现过程,考虑到数据长度问题,但是发送的数据包长度可能不同,每次只能发送一个数据包,如何处理这个问题呢?此处用共用体较好解决了这个问题,共用体所占用的内存只能是共用体中的内存最大的那个元素,比如说数据包Packet_base package_base、PACKDATA_Energy package_energy所占内存大小不一样,一个128Bytes另外一个200Bytes,最终加上head和tail以及校验和、数据包一起发送的时候长度就是变动的。如果不使用union,那么发送的数据长度局势固定的,可能会浪费内存,效率低,甚至还会出现无用错误数据,接收端不好处理。

采用以上结构体用union,union内又使用其他的结构体方式能够灵活处理数据传输。关于结构体、共用体、枚举类型更多的使用方法可以参看一些官方库函数。

1 0