Last active
April 6, 2018 09:09
-
-
Save liweinan/36e55fdd086e6a21f01429fe5871656f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> // malloc和free函数定义在这个library里。 | |
#include <stdio.h> // printf函数定义在这个地址里。 | |
struct _listADT { | |
int size; // list的大小 | |
int *data; // list数据的实际内存位置,是一块连续的内存空间。 | |
int *head; // list的数据的起始位置 | |
// 函数的指针,指向add()方法的实际实现。 | |
// 因为C语言没有class的概念,没法把对list的方法和数据都封装到一个class里面, | |
// 所以就通过在struct里面定义函数指针的方式来实现一个类似class的形式。 | |
void (*add)(struct _listADT*, int); // 我们约定这个list保存的是int类型的数据。这样数据类型一致, | |
// 才能保证访问第N个数据的时候,内存位置是可以被计算的,否则就会出错。 | |
// 而编译器也不会允许你保存不同类型的数据的。 | |
// 如果你一定要保存不同类型的数据,就像Python里面实现的Bag那样, | |
// 那你可以拿list保存每一个item的地址,也就是int * | |
// 这样,你的list里面的每一个item,其实都是这个item的地址,而不是数据本身 | |
// 而地址的数据类型和大小是一致的,就是long,这样也没有问题 | |
// 但是我们这个例子不用考虑这么复杂,就考虑只保存全部是int数据的情况 | |
// 就可以了。 | |
void (*delete)(struct _listADT*, int); // 删掉第index个item,index是int类型数据 | |
}; | |
// 简化一下代码,接下来写`List`,就可以代替`struct _listADT`了,少写点字 | |
typedef struct _listADT List; | |
// 下面这两个函数是具体实现,下面要连接到_listADT的对应的函数指针上去。 | |
void listAdd(List* self, int value) { | |
printf("ADD AN ITEM\n"); | |
} | |
void listDelete(List* self, int idx) { | |
printf("DELETE AN ITEM\n"); | |
} | |
List* CreateList() { | |
int default_size = 100; // 创建一个大小默认为100的list(list和linkedList不同,需要一个初始的大小)。 | |
// 这个list默认可以保存100个数据,然后后续如果不够,再在add方法里面扩展内存。 | |
List* newList = malloc(sizeof(List)); // 申请了heap内存,保存这个动态创建的List数据的实例。 | |
newList->size = default_size; // list里面items的初始个数。(linked list不需要初始个数,动态增减就可以) | |
int* listData = malloc(sizeof(default_size * sizeof(int))); // 申请了heap内存,用来保存items数据。约定items都是int类型的数据。 | |
newList->data = listData; // 把申请到的内存的地址的起始位置连接到struct的data这个指针上面。 | |
newList->add = &listAdd; // 把add这个函数指针对应的具体实现,连接到listAdd函数上。(都是通过内存指针完成的,让add指向listAdd的函数地址。) | |
// 在C的世界里,所有数据,代码的地址,都是可以被引用的。 | |
// 但代码的地址只能被引用,数据只读,不可写,防止process在执行的过程中可以动态地修改自身的代码。 | |
// 这是出去安全角度,操作系统做的内存防护工作。 | |
newList->delete = &listDelete; // 同理,把delete方法指向listDelete函数的具体实现地址。 | |
return newList; // 返回这个新创建的list instance。 | |
} | |
int main() { | |
List* list = CreateList(); | |
list->add(list, 'x'); | |
list->delete(list, 0); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment