如何理解并应用C语言里自己构造的结构体(结构体名字/别名/指针)

【问1】

先构建了一个结构体,里面的screen_illuminate,screen_illuminate_t,*screen_illuminate_pt分别是什么意思,分别有什么用途,为啥要这样写?
typedef struct screen_illuminate
{
    uint16_t chn;
    uint16_t value;
}screen_illuminate_t, *screen_illuminate_pt;

然后在某一个函数里写一行这个代码:screen_illuminate_t screen_illuminate_chn;
这个的意思是在这个函数里构建一个和screen_illuminate_t一样的,但是名为screen_illuminate_chn的结构体吗?然后就能在screen_illuminate_chn上操作,而不会影响screen_illuminate_t?
 

【先上自己可能并不严谨,偏应用性的理解】

  • typedef struct screen_illuminate { ... }: 这是一个结构体定义,名为 screen_illuminate

  • screen_illuminate_t: 别名,类似uint16_t这种写法,比如screen_illuminate_t A;说明你构造了一个screen_illuminate类型的结构体A,你对A做操作,不会影响screen_illuminate

  • *screen_illuminate_pt: 指针别名。screen_illuminate_pt 表示指向 screen_illuminate 结构体的指针。比如screen_illuminate_pt A;你对A做操作,是会影响screen_illuminate的。

【若我有理解错误的地方,请不吝赐教!非常感谢!】

这里引申一个点,关于怎么在其他的函数里操作结构体(希望大家明白且会用)

比如A.h里,你是这样定义protocol结构体的:

//A.h

typedef struct protocol
{
    uint8_t  cmd;
    uint8_t  Control_Domain[LAMP_MAX_NUM_define / 8];
}t_protocol, * pt_protocol;

//A.c

t_protocol protocol ;//定义一个protocol结构体类型的实例,取名叫protocol;

void Uart_Handler(pt_protocol protocol)

//这里的protocol是指针,所以下面使用->这个符号去操作protocol
{
    update_device_domain(protocol->Control_Domain);

} 

然后我在B.h里定义了一个screen结构体,里面我需要包含和protocol这个结构体类型,我取名叫data:

这就分两种情况,

第一种:我想通过操作B.c里screen结构体里的data,直接和A.c一起去控制protocol的值

//B.h

typedef struct screen
{
    pt_protocol data;//我想通过操作data,直接改变protocol里的值,所以data是指针
    uint16_t page_num;   
}t_screen, *pt_screen;

那么B.c里应该怎么写呢?首先你还是把t_protocol protocol思考成和uint8_t aaaa = 0;差不多的东西,aaaa如果要想被其他点c文件的函数用,它就要是一个全局变量,同样的,如果需要protocol变成一个全局的结构体,那么可以A.h里再写一行:extern  t_protocol protocol;

//B.c

t_screen screen;

void Uart_ScreenHandler(pt_screen screen)//我写在BBBB.c里,声明在BBBB.h里
{

        screen.data = &protocol;//在函数里写一行
        update_device_domain(screen.data->Control_Domain);

}

第二种:我操作B.c里screen结构体里的data,不会影响A.c的protocol的值

//B.h

typedef struct screen//我定义在BBBB.h里
{
    t_protocol data2;//我想通过操作data2,不会改变protocol里的值
    uint16_t page_num;   
}t_screen, *pt_screen;

//B.c

t_screen screen;

void Uart_ScreenHandler(pt_screen screen)//我写在BBBB.c里,声明在BBBB.h里
{
    update_device_domain(screen->data.Control_Domain);

}


第一种pt_protocol data1;
data1 是一个指向 t_protocol 结构体的指针,你需要通过 -> 操作符来访问 data 指向的结构体的成员

第二种t_protocol data2;
data2 是 t_protocol 结构体的一个实例,你需要通过.操作符来访问 data2 的成员

总结:
使用 -> 是通过指向结构体或联合体的指针来访问其成员,适用于操作指向结构体或联合体的指针。
使用 . 是直接访问结构体或联合体的成员,适用于操作结构体或联合体的实例。

---------------------------------------------------------------------------------------

【更规范一些的答复】

让我们逐步解释这些概念和代码段的含义和用法。

1. 结构体定义

首先,让我们看一下你提供的结构体定义:

typedef struct screen_illuminate {

uint16_t chn;

uint16_t value;

} screen_illuminate_t, *screen_illuminate_pt;

  • typedef struct screen_illuminate { ... }: 这是一个结构体定义,名为 screen_illuminate,其中包含两个成员 chnvalue,都是 uint16_t 类型。

  • screen_illuminate_t: 这是一个结构体 screen_illuminate 的别名,也就是说,screen_illuminate_tstruct screen_illuminate 在此处是等价的,可以互换使用。

  • *screen_illuminate_pt: 这是一个指向 screen_illuminate 结构体的指针类型的别名。screen_illuminate_pt 表示指向 screen_illuminate 结构体的指针。

所以,这段代码做了两件事:

  • 定义了一个结构体 screen_illuminate,其中有两个成员 chn 和 value
  • 创建了两个别名:screen_illuminate_t 表示结构体 screen_illuminatescreen_illuminate_pt 表示指向结构体 screen_illuminate 的指针。

2. 函数内部的变量声明

现在来看你提到的在函数内部的代码:

screen_illuminate_t screen_illuminate_chn;

这行代码的意思是在当前函数内部定义了一个名为 screen_illuminate_chn 的变量,它的类型是 screen_illuminate_t,也就是之前定义的结构体 screen_illuminate

  • screen_illuminate_t 在这里被用作变量类型,因此 screen_illuminate_chn 是一个名为 screen_illuminate_t 的结构体变量。

解释和用途

为什么要这样写?

  • 代码复用和简化: 使用 typedef 可以简化代码,使得定义结构体和相应的指针更为简洁和可读。
  • 清晰的代码结构: 通过 typedef 创建别名,可以使代码更加清晰和易于理解,特别是在涉及多次使用结构体和指针时。
  • 避免混淆和错误: 使用 typedef 可以减少因为类型不匹配或错误使用指针而引起的错误。

关于你的问题:在函数内部使用 screen_illuminate_t screen_illuminate_chn; 只是在当前函数的作用域中定义了一个新的结构体变量 screen_illuminate_chn,它的类型是 screen_illuminate_t。这不会影响到 screen_illuminate_t 类型的其他变量,因为每个变量都有自己的存储空间和作用域。

总结来说,这种定义方式使得代码更加模块化和可维护,同时确保了变量的类型和指针的正确使用。

【问2】

还有一种是这样用的 ,screen_illuminate_pt screen_illuminate_chn;它和screen_illuminate_t screen_illuminate_chn;的区别是什么?

【答2】

在你提到的这两种声明方式中:

  1. screen_illuminate_t screen_illuminate_chn;

    这种声明方式直接定义了一个 screen_illuminate_t 类型的结构体变量 screen_illuminate_chn。这意味着 screen_illuminate_chn 是一个具体的结构体变量,它占据了实际的存储空间,可以直接访问和操作其成员 chnvalue

    screen_illuminate_t screen_illuminate_chn;screen_illuminate_chn.chn = 1; screen_illuminate_chn.value = 100;
  2. screen_illuminate_pt screen_illuminate_chn;

    这种声明方式定义了一个指针变量 screen_illuminate_chn,其类型为 screen_illuminate_pt,即指向 screen_illuminate_t 类型的指针。这意味着 screen_illuminate_chn 并不直接存储结构体的数据,而是存储结构体的地址,需要通过解引用操作来访问结构体的成员。

    screen_illuminate_t illuminate_instance; screen_illuminate_pt screen_illuminate_chn = &illuminate_instance; screen_illuminate_chn->chn = 2; screen_illuminate_chn->value = 200;

    在这个例子中,screen_illuminate_chn 是一个指向 illuminate_instance 的指针,可以通过 -> 运算符访问 illuminate_instance 的成员。

区别总结:

  • screen_illuminate_t screen_illuminate_chn; 声明一个结构体变量,直接存储结构体数据。
  • screen_illuminate_pt screen_illuminate_chn; 声明一个结构体指针变量,存储结构体的地址,需要通过解引用来访问结构体成员。

选择使用哪种方式取决于具体的需求和设计。通常情况下:

  • 如果你需要直接操作结构体的数据,应该使用 screen_illuminate_t screen_illuminate_chn;
  • 如果你需要传递结构体的引用或者在函数间共享结构体数据,可以使用 screen_illuminate_pt screen_illuminate_chn;

这些声明方式在不同的情况下能提供更灵活和合适的选择。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值