打印
[C语言]

C 结构变量对象化操作

[复制链接]
3060|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
aple0807|  楼主 | 2021-9-26 16:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 aple0807 于 2021-9-26 16:36 编辑

在单片机的C语言项目中,会大量采用结构体来封装操作对象数据模型,然后用指针传入函数来处理数据。
当系统中创建多个操作对象,且模型有多个处理函数时,直接调用函数处理结构体,可读性将会变差,且书写不方便,我已经深受其害,总是书写混淆。
此时如果引入C++中对象成员函数的方式来调用接口,可读性将会大幅提高,也会极大降低书写错误率。

下面举例阐述C结构对象操作的方法,仅适用于全局对象操作。
例如我们使用的内存管理,当系统中有SRAM,SDRAM,CCM等地址不连续的内存需要管理时。

我们创建如下结构来描述内存。

mem_alloc.h文件
// 对象运行信息
typedef struct
{
    uu8 init_ok;
    uu16 used_block;
} multi_malloc_info_type;


// 对象API成员
typedef struct
{
    void * (*malloc)(size_t size);
    void * (*calloc)(size_t num, size_t size);
    void * (*realloc)(void *, size_t size);
    void(*free)(void *);
    uu16(*perused)(void);
} multi_malloc_api_type;

// 对象结构
typedef struct
{
    uu64 *mem;                            // 内存基址
    uu16 *mem_tab;                        // 分配表
    uu16 mem_size;                        // 内存尺寸
    uu16 block_size;                    // 块大小-分配单位
    uu16 block_amount;                    // 块数量
    uu16(*lock)(void);                    // 互斥锁请求
    void(*unlock)(void);                // 互斥锁释放
    multi_malloc_info_type *info;        // 运行信息-必要
    const multi_malloc_api_type *api;    // 对象接口-可选
} multi_malloc_type;



下面函数操作内存,
mem_alloc.c文件
void multi_malloc_init(const multi_malloc_type*obj)
{
};
void * multi_malloc(const multi_malloc_type*obj, size_t size)
{
};
void * multi_calloc(const multi_malloc_type*obj, size_t num, size_t size)
{
};
void * multi_realloc(const multi_malloc_type*obj, void *, size_t size)
{
};
void multi_free(const multi_malloc_type*obj, void *)
{
};
uu16 multi_malloc_perused(const multi_malloc_type *obj)
{
};


通常我们直接调用这里的函数来操作对象,
比如 :
multi_free(&obj_sram, ptr);
multi_free(&obj_ccram, ptr);
当程序中有很多这种写法时,往往会搞错对象,造成很隐蔽的错误难以发现。
为了让程序看起来更加简单明了,我们将这一组函数进行封装,然后挂载到对象结构的.api成员上。

方法如下:        
使用宏创建一组函数,配置内存时将函数列表连接在结构体的 .api变量上。
这里实际是要创建一个 multi_malloc_api_type 变量,内容是名字为 “obj”的函数成员
mem_alloc.c文件++
#define multi_malloc_api_name(obj)    &obj##_api
#define multi_malloc_api_ref(obj)    const multi_malloc_api_type  obj##_api
#define multi_malloc_api_link(obj)    obj.api=obj##_api    // 非const结构使用

#define multi_malloc_api_make(obj)                                        \
    void * obj##_malloc(size_t size){return multi_malloc(&obj, size);}    \
    void * obj##_calloc(size_t num, size_t size)                          \
            {return multi_calloc(&obj, num, size);}                       \
    void * obj##_realloc(void *p, size_t size)                            \
            {return multi_realloc(&obj, p, size);}                        \
    void obj##_free(void *p){ multi_free(&obj, p);}                       \
    uu16 obj##_perused(void){ return multi_malloc_perused(&obj);}         \
    const multi_malloc_api_type  obj##_api = {                            \
        obj##_malloc,                                                     \
        obj##_calloc,                                                     \
        obj##_realloc,                                                    \
        obj##_free,                                                       \
        obj##_perused                                                     \
    }


创建对象
该步骤用于生成一个具体可操作的对象,可以创建多个。

mem_alloc.c文件++
uu64 sram_map[1024 / 8] @".sram";            // 内存池
uu16 sram_tab[32] @".sram";                  // 内存分配表
multi_malloc_info_type sram_info = { 0 };    // 工作信息
uu16 sram_lock(void)
{
    return 0;
}               
// 申请互斥锁
void sram_unlock(void)
{
}                    
// 释放互斥锁
multi_malloc_api_ref(mem_sram);               // 接口引用声明
const multi_malloc_type mem_sram =            // 信息描述
{
    sram_map,
    sram_tab,
    sizeof(sram_map),
    32,
    sizeof(sram_map) / 32,
    sram_lock,
    sram_unlock,
    &sram_info,
    multi_malloc_api_name(mem_sram)           // 关联到API
};
multi_malloc_api_make(mem_sram);              // 创建API接口



应用程序中可以如下方法使用对象接口,这样程序书写可以借助编辑器的自动补全功能,书写十分方便
extern const multi_malloc_type mem_sram;

ptr = mem_sram.api->malloc(100);
mem_sram.api->free(ptr);




使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

309

帖子

2

粉丝