jeonkc 2018-09-20
不知道这个题目是否合适,因为C语言是没有模板的,好吧,我承认,用集合来描述比较合适。下面是项目地址:
https://github.com/mtaxot/c-collection
那么强大的C语言,当打开vim,想干什么却不得不重造轮子,想想就累。其实Java为什么那么好用,很大一部分原因是Java没有指针,还有一部分原因是Java有集合框架,拿过来ArrayList, HashMap 用起来相当的方便。而C++因为STL是标准库,所以用起来也好方便。为什么C语言这么悲催,找个哈希表都这么难,哎,轮子还是得造。
java用的是集合框架,当然我这个目前还谈不上一个功能全面的C语言集合库,实现这个集合功能的想法来自Linux内核代码的list.h,当然我的实现和内核的实现还是很不一样的,我这个实现比较简单,当然没有内核的实现那么通用。不过对于一般的工程来说,这个实现版本足够通用。下面介绍一下实现思路。
先从结构体说起,我们知道结构体变量的首地址在一般情况下等于结构体变量第一个成员的首地址,当然有些编译器并不这么做,但是是少数派,我们暂且不管。所以在移植方面,这个框架做的并不那么完美,希望大家能献计献策。 基于地址相同的这个事实,我们可以给这个框架的设计加入一些“面向对象的思想”。以链表为例进行说明:
1.我们先定义一个通用的结构:
typedef struct _list_item { struct _list_item *prev; struct _list_item *next; }list_item;
我们的思想就是,增删改查只针对这个通用的结构进行,那么我们的业务数据是如何被操作的呢,这就需要用到我们上面那个地址相等的事实,稍作修饰即可。
typedef struct sutd { AS_LIST_ITEM;//关键无比的宏,逻辑上可以认为stud_t “继承”了这个list_item int id; char *name; }stud_t;
AS_LIST_ITEM 是一个宏:
#define AS_LIST_ITEM list_item __list_item
这样当我们操作链表的时候只需要把我们的stud_t 当成一个指针传入增删改查函数即可,增删改查函数内部把指针当做 list_item类型来操作,同样也会返回给我们这个类型的指针,业务层收到这个指针后,只需要强制类型转换到stud_t即可。
对于有些平台,如果第一个变量的首地址跟结构体变量的首地址不等,而是逆序摆放,那么调整宏的位置到最后即可.
插入一张图便于大家理解,蓝色的就是我们的list_item,我们的确没有必要针对特定类型进行串链表
黑色的方格就是我们的业务层的结构体,怎么样,明白了吧。array,map同理