C语言中的struct结构体、union联合体、enum枚举和typedef

发布时间 2023-12-06 14:37:02作者: HAOstudio

C语言中的struct结构体、union联合体、enum枚举和typedef

结构体struct

结构体是C编程中另一种用户自定义的可用的数据类型,它允许存储不同类型的数据项。
结构体中的数据成员可以是基本数据类型(如 int、float、char等),也可以是其他结构体类型、指针类型等。

关键字:struct

struct结构体的一般格式如下:(引自:菜鸟教程)

struct tag { 
    member-list;
    member-list;
    member-list;  
    ...
} variable-list ;

1. 结构体的定义

有以下几种不同的定义结构体的方式:

(1) 先定义结构体(显式定义),后定义结构体变量

struct set_of_mdata
{
    int     mdata1;
    float   mdata2;
    char    mdata3;
    double  mdata4[4];
};
struct set_of_mdata som1, som2; //定义结构体变量

(2) 定义结构体(显式定义)的同时定义结构体变量,还可以再次使用结构体声明变量

struct set_of_mdata
{
    int     mdata1;
    float   mdata2;
    char    mdata3;
    double  mdata4[4];
} som1, som2;
struct set_of_mdata som3;

(3) 定义结构体(隐式定义)的同时定义结构体变量,不可以再次使用结构体声明变量

struct
{
    int     mdata1;
    float   mdata2;
    char    mdata3;
    double  mdata4[4];
} som1, som2;

(4) 使用typedef为结构体起别名(显式定义),通过别名定义结构体变量

typedef struct
{
    int     mdata1;
    float   mdata2;
    char    mdata3;
    double  mdata4[4];
} mdata_def;
mdata_def som1, som2;

2. 对结构体的一些操作

通过下面一段代码,来了解一下如何对结构体进行赋值和操作:

#include <stdio.h>

//定义结构体
struct set_of_mdata
{
    int     mdata1;
    float   mdata2;
    char    mdata3;
    double  mdata4[4];
};
struct set_of_mdata som = {10, 3.14, 'd', {2.0, 3.0, 4.0, 5.0}}; //在定义结构体变量时进行初始化

int main()
{
    //通过.运算符访问或修改结构体成员
    printf("mdata1:%d \n", som.mdata1);
    printf("mdata2:%f \n", som.mdata2);
    printf("mdata3:%c \n", som.mdata3);
    printf("mdata4:%f \n", som.mdata4[2]);
    //定义指向结构体的指针
    struct set_of_mdata *mdata_ptr = &som;
    //通过->运算符访问或修改结构体指针所指结构体的成员
    mdata_ptr->mdata1 = 150;
    mdata_ptr->mdata2 = 6.28;
    printf("mdata1:%d \n", mdata_ptr->mdata1);
    printf("mdata2:%f \n", mdata_ptr->mdata2);
}

输出结果如下:
代码运行结果

知识点:
(1) 结构体成员的初始化
在定义结构体变量的同时,通过花括号{value1, value2,...}赋给该结构体成员初始值。

(2) 访问结构体成员
通过.运算符访问或修改结构体成员。

(3) 定义指向结构体的指针
和普通变量的指针定义方式相同。

(4) 结构体指针访问成员
通过->运算符访问或修改结构体指针所指结构体的成员。

3. 结构体的大小

联合体union

联合体是类似结构体struct的一种数据结构,两者的区别在于联合体的成员共享同一个内存位置,也就是说,联合体中的所有成员都是从相同的内存地址开始。
一个union联合体只配置一个足够大的空间以来容纳最大长度的数据成员

关键字:union

1. 联合体的定义

在定义上和结构体完全相同,将struct关键字改为union关键字即可。

(1) 先定义联合体(显式定义),后定义联合体变量

union udata
{
    float ud1;
    char  ud2[3];
};
union udata udata1, udata2;

(2) 定义联合体(显式定义)的同时定义联合体变量,还可以再次使用联合体声明变量

union udata
{
    float ud1;
    char  ud2[3];
}udata1, udata2;
union udata udata3;

(3) 定义联合体(隐式定义)的同时定义联合体变量,不可以再次使用联合体声明变量

union
{
    float ud1;
    char  ud2[3];
}udata1, udata2;

(4) 使用typedef为联合体起别名(显式定义),通过别名定义联合体变量

typedef union
{
    float ud1;
    char  ud2[3];
}udata_def;
udata_def udata1, udata2;

2.对联合体的一些操作

操作与结构体的操作完全相同。参考对结构体的一些操作一节。

3. 联合体的大小

枚举enum

枚举是 C 语言中的一种基本数据类型,用于定义一组具有离散值的常量,它可以让数据更简洁,更易读。
每个枚举常量可以用一个标识符来表示,也可以为它们指定一个整数值,如果没有指定,那么默认从 0 开始递增。

关键字:enum

枚举类型经常用于定义各种状态,用作函数的返回值,来指示函数的行为。

下面是STM32官方库的一些枚举类型的定义:

//GPIO Bit SET and Bit RESET enumeration
typedef enum
{
  GPIO_PIN_RESET = 0U,
  GPIO_PIN_SET
} GPIO_PinState;

//HAL ADC Callback ID enumeration definition
typedef enum
{
  HAL_ADC_CONVERSION_COMPLETE_CB_ID     = 0x00U,  /*!< ADC conversion complete callback ID */
  HAL_ADC_CONVERSION_HALF_CB_ID         = 0x01U,  /*!< ADC conversion DMA half-transfer callback ID */
  HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID   = 0x02U,  /*!< ADC analog watchdog 1 callback ID */
  HAL_ADC_ERROR_CB_ID                   = 0x03U,  /*!< ADC error callback ID */
  HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID = 0x04U,  /*!< ADC group injected conversion complete callback ID */
  HAL_ADC_INJ_QUEUE_OVEFLOW_CB_ID       = 0x05U,  /*!< ADC group injected context queue overflow callback ID */
  HAL_ADC_LEVEL_OUT_OF_WINDOW_2_CB_ID   = 0x06U,  /*!< ADC analog watchdog 2 callback ID */
  HAL_ADC_LEVEL_OUT_OF_WINDOW_3_CB_ID   = 0x07U,  /*!< ADC analog watchdog 3 callback ID */
  HAL_ADC_END_OF_SAMPLING_CB_ID         = 0x08U,  /*!< ADC end of sampling callback ID */
  HAL_ADC_MSPINIT_CB_ID                 = 0x09U,  /*!< ADC Msp Init callback ID          */
  HAL_ADC_MSPDEINIT_CB_ID               = 0x0AU   /*!< ADC Msp DeInit callback ID        */
} HAL_ADC_CallbackIDTypeDef

1. 枚举类型的定义

枚举类型的定义一般为:

enum 枚举类型 {枚举值1, 枚举值2, ......};

区别点:枚举类型花括号里的值是使用逗号,分隔的,而结构体和联合体是使用;分隔的。

(1) 先定义枚举类型(显式定义),后定义枚举变量

enum STATE
{
    OK      = 0 ,
    WARN        ,
    ERROR       ,
    STOP
};
enum STATE mState;

(2) 定义枚举类型(显式定义)的同时定义枚举变量,还可以再次使用枚举类型声明变量

enum STATE
{
    OK      = 0 ,
    WARN        ,
    ERROR       ,
    STOP
}mState1;
enum STATE mState2;

(3) 定义枚举类型(隐式定义)的同时定义枚举变量,不可以再次使用枚举类型声明变量

enum
{
    OK      = 0 ,
    WARN        ,
    ERROR       ,
    STOP
}mState1;

(4) 使用typedef为枚举类型起别名(显式定义),通过别名定义枚举变量

typedef enum
{
    OK      = 0 ,
    WARN        ,
    ERROR       ,
    STOP
} STATE_DEF;
STATE_DEF mState1, mState2;

枚举类型中的枚举值的标识符是唯一的,不能与其他宏定义标识符重名。

2. 对枚举类型的一些操作

(1) 初始化枚举变量,在定义的时候进行初始化

typedef enum
{
    OK      = 0 ,
    WARN        ,
    ERROR       ,
    STOP
} STATE_DEF;
STATE_DEF mState1 = WARN;
STATE_DEF mState2 = OK;

(2) 在程序当中修改枚举变量

typedef enum
{
    OK      = 0 ,
    WARN        ,
    ERROR       ,
    STOP
} STATE_DEF;
STATE_DEF mState1 = WARN;

mState1 = OK;   //在程序当中修改枚举变量

3. 枚举类型的大小