野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 20183|回复: 2

C语言——结构体总结

[复制链接]
发表于 2016-9-13 09:05:28 | 显示全部楼层 |阅读模式
本帖最后由 1838039453 于 2016-9-13 09:08 编辑

C语言——结构体

1、结构体的作用:个人理解,结构体就是把一堆相关的数据打包成一个结构,使其放在一块内存区域。——项目之中尽量使用结构体,而不要单独使用数组。

2、结构体的声明与定义
规范:
(1)如果此结构体在多个文件中使用就放在头文件中(.h文件中);如果此结构体只在本文件中使用,则放在源文件中(.c文件中),并加以static限定。
(2)如果是用typedef起别名,则以_t作为后缀;如果是用static限定的则不用_t后缀。
  1. typedef __packed struct
  2. {
  3.     uint8_t datetime[6];    // 年月日,时分秒 (BCD) -- 连续驾驶开始/结束时间
  4.     int16_t altitude;  // 海拔
  5.     int32_t longitude; // 经度
  6.     int32_t latitude;  // 纬度
  7. } gbt19056_fatigue_info_t;// __packed表示一字节对齐,单片机编程中常用
  8. // gbt19056_fatigue_info_t相当于类型名,类似于int,float之类的

  9. static struct
  10. {
  11.     rtc_timer_t timer_check;
  12.     uint16_t attr; // 区域属性
  13.     ca8gps_event_data_t event;
  14. } t808_area;
复制代码
结构体声明的时候一定要注意字节对齐的问题,加上__packed为了一字节对齐,否则默认是4字节对齐的。
定义和声明:定义分配内存,声明不分配内存。

3、结构体的初始化接口
规范:函数名大写的是对外接口,函数名全小写加下划线的是对内接口。
typedef重命名的要先定义一个变量,然后再使用,如下:
gbt19056_fatigue_info_t info1; // 访问则是info1.altitude = 0x012;
gbt19056_fatigue_info_t *info2; // 访问则是info2->altitude = 0x012;
static限定的则直接使用,t808_area. attr = 0x55;
一般项目中要写初始化函数:
  1. void gbt19056_fatigue_init(void)
  2. {
  3.     memset(&info, 0, sizeof(gbt19056_fatigue_info_t));

  4.     memcpy(info2->datetime, date, sizeof(info2->datetime));
  5.     info2->altitude = 0;
  6.     info2->longitude = 0x7FFFFFFF;
  7.     info2->latitude = 0x7FFFFFFF;
  8. }
复制代码

4、结构体访问接口
比较大型一点的项目之中,多个文件会用到一些结构中的成员,因此写成接口形式。
规范:一般少使用全局变量,需要某些值的时候以函数接口形式给予。
  1. uint16_t T808AreaAddr(void)
  2. {
  3.     return t808_area. attr;
  4. }

  5. void GBT19056FatigueTime(char *data)
  6. {
  7.     memcpy(data, info2->datetime, sizeof(info2->datetime));
  8. }
复制代码

5、结构体中一些技巧
处理批量类似事情:
  1. // 一个命令字对应一个处理函数,用for循环扫描
  2. // 命令字有的用枚举, 有的用宏
  3. typedef enum
  4. {
  5.     T808_CUSTOM_CAMERA_COUNT      = 1,
  6.     T808_CUSTOM_DISTANCE_TYPE     = 2,
  7.     T808_CUSTOM_OIL               = 3,
  8.     T808_CUSTOM_VERSION           = 4
  9. } t808_t;
  10. // 再三强调,起别名的类型一定要加_t后缀以示区分
  11. typedef uint8_t (*handler_t)(char *data, uint8_t length);

  12. typedef struct
  13. {
  14.     // 变量类型和函数参数随机应变
  15.     uint8_t cmd;
  16.     uint8_t length;
  17.     handler_t hander;
  18. } t808_custom_entry_t ;

  19. static uint8_t t808_custom_camera_count(char *data, uint8_t length);
  20. static uint8_t t808_custom_disdance _type(char *data, uint8_t length);
  21. static uint8_t t808_custom_oil(char *data, uint8_t length);
  22. static uint8_t t808_custom_version(char *data, uint8_t length);

  23. //===========================================================
  24. // 定义好结构之后,用数组装载整个命令及其处理函数
  25. static const  t808_custom_entry_t t808_custom_entries[] =
  26. {
  27.      {T808_CUSTOM_CAMERA_COUNT, 1, t808_custom_camera_count},
  28.     {T808_CUSTOM_DISTANCE_TYPE, 1, t808_custom_disdance _type},
  29.     {T808_CUSTOM_OIL, 22, t808_custom_oil},
  30.     {T808_CUSTOM_VERSION, 14, t808_custom_version},
  31. };

  32. // 在一个函数中用for循环扫描
  33. static void
  34. custom_setting(client_t*client, t808_hdr_t *request, uint16_t length)
  35. {
  36.     t808_custom_entry_t*entry;

  37.     for(entry = t808_custom_entries; entry->handler; ++entry)
  38.     {
  39.         if(entry->cmd == request->cmd)
  40.         {
  41.             entry->handler(data, length); // 只是一个轮廓,仅供参考

  42.              break;
  43.         }
  44.     }
  45. }
复制代码


回复

使用道具 举报

发表于 2016-9-13 09:14:32 | 显示全部楼层
结构体用得好,还能实现面向对象的功能
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-13 09:30:12 | 显示全部楼层
随风 发表于 2016-9-13 09:14
结构体用得好,还能实现面向对象的功能

当然啊。C语言就靠这个结构体模拟C++中的面相对象了。用结构体还是为了防止变量多乱的问题。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2025-12-12 07:52 , Processed in 0.039841 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表