Last active
June 10, 2016 13:53
-
-
Save alphaKAI/93fd9ab092b27fc6143975c959017bcf to your computer and use it in GitHub Desktop.
データとリストを分離し、任意の型で簡単に単方向リストを実装できるようにするサンプル(Linuxカーネルでの実装を参考にしました。)
This file contains hidden or 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 <stdbool.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#define container_of(ptr, type, member) ({ \ | |
const typeof( ((type *)0)->member ) *__mptr = (ptr); \ | |
(type *)( (char *)__mptr - offsetof(type,member) );}) | |
#ifdef __compiler_offsetof | |
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER) | |
#else | |
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) | |
#endif | |
void *xmalloc(size_t size) { | |
void *ret; | |
ret = malloc(size); | |
if (ret == NULL) { | |
exit(EXIT_FAILURE); | |
} | |
return ret; | |
} | |
typedef struct _node { | |
struct _node* next; | |
} Node; | |
void free_all_node(Node* node) { | |
if (node != NULL) { | |
if (node->next != NULL) { | |
free_all_node(node->next); | |
} | |
free(node); | |
} | |
} | |
void free_nodes(Node* node) { | |
if (node->next != NULL) { | |
free_nodes(node->next); | |
} | |
free(node); | |
} | |
Node* get_last_node(Node* node) { | |
Node* thisNode; | |
for (thisNode = node; thisNode->next != NULL; thisNode = thisNode->next) ; | |
return thisNode; | |
} | |
bool is_singlelist_empty(Node* node) { | |
return node == NULL; | |
} | |
void add_node(Node* parent, Node* child) { | |
child->next = NULL; | |
if (is_singlelist_empty(parent)) { | |
parent = child; | |
} else { | |
Node* lastNode = get_last_node(parent); | |
parent->next = child; | |
} | |
} | |
struct IntList { | |
Node* node; | |
int value; | |
}; | |
void add_int_value(struct IntList* parent, int* value) { | |
struct IntList* child = (struct IntList*)xmalloc(sizeof(struct IntList)); | |
child->node = (Node*)xmalloc(sizeof(Node)); | |
child->value = *value; | |
add_node(parent->node, child->node); | |
} | |
struct IntList* get_int_value(int* value) { | |
struct IntList* il = container_of(value, struct IntList, value); | |
return il; | |
} | |
void testIntList() { | |
struct IntList parent = {}; | |
parent.node = (Node*)xmalloc(sizeof(Node)); | |
parent.node->next = NULL; | |
for (int i = 0; i < 10; i++) { | |
add_int_value(&parent, &i); | |
} | |
for (int i = 0; i < 10; i++) { | |
struct IntList* il = get_int_value(&i); | |
printf("NUM:%d\n", il->value); | |
} | |
free_all_node(parent.node); | |
} | |
struct CharList { | |
Node* node; | |
char* value; | |
}; | |
void add_char_value(struct CharList* parent, char* value) { | |
struct CharList* child = (struct CharList*)xmalloc(sizeof(struct CharList)); | |
child->node = (Node*)xmalloc(sizeof(Node)); | |
child->value = value; | |
add_node(parent->node, child->node); | |
} | |
struct CharList* get_char_value(char* value) { | |
struct CharList* cl = container_of(&value, struct CharList, value); | |
return cl; | |
} | |
void testCharList() { | |
struct CharList parent; | |
parent.node = (Node*)xmalloc(sizeof(Node)); | |
parent.node->next = NULL; | |
char* chars[] = { | |
"value1", | |
"value2", | |
"value3", | |
"value4" | |
}; | |
for (int i = 0; i < 4; i++) { | |
add_char_value(&parent, chars[i]); | |
} | |
for (int i = 0; i < 4; i++) { | |
struct CharList* cl = get_char_value(chars[i]); | |
printf("CHAR:%s\n", cl->value); | |
} | |
free_all_node(parent.node); | |
} | |
int main() { | |
testIntList(); | |
testCharList(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment