用C实现通用列表
#include <stdio.h>
typedef void *QUEUE[2];
/* Private macros. */
#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0]))
#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1]))
#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q)))
#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q)))
/* Public macros. */
#define QUEUE_DATA(ptr, type, field) \
((type *) ((char *) (ptr) - ((char *) &((type *) 0)->field)))
#define QUEUE_FOREACH(q, h) \
for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))
#define QUEUE_EMPTY(q) \
((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q))
#define QUEUE_HEAD(q) \
(QUEUE_NEXT(q))
#define QUEUE_INIT(q) \
do { \
QUEUE_NEXT(q) = (q); \
QUEUE_PREV(q) = (q); \
} \
while (0)
#define QUEUE_ADD(h, n) \
do { \
QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \
QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \
QUEUE_PREV(h) = QUEUE_PREV(n); \
QUEUE_PREV_NEXT(h) = (h); \
} \
while (0)
#define QUEUE_SPLIT(h, q, n) \
do { \
QUEUE_PREV(n) = QUEUE_PREV(h); \
QUEUE_PREV_NEXT(n) = (n); \
QUEUE_NEXT(n) = (q); \
QUEUE_PREV(h) = QUEUE_PREV(q); \
QUEUE_PREV_NEXT(h) = (h); \
QUEUE_PREV(q) = (n); \
} \
while (0)
#define QUEUE_INSERT_HEAD(h, q) \
do { \
QUEUE_NEXT(q) = QUEUE_NEXT(h); \
QUEUE_PREV(q) = (h); \
QUEUE_NEXT_PREV(q) = (q); \
QUEUE_NEXT(h) = (q); \
} \
while (0)
#define QUEUE_INSERT_TAIL(h, q) \
do { \
QUEUE_NEXT(q) = (h); \
QUEUE_PREV(q) = QUEUE_PREV(h); \
QUEUE_PREV_NEXT(q) = (q); \
QUEUE_PREV(h) = (q); \
} \
while (0)
#define QUEUE_REMOVE(q) \
do { \
QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \
QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \
} \
while (0)
/**
* A pointer to a list node.
*/
static QUEUE* q;
/**
* Our circulary list.
*/
static QUEUE queue;
/**
* Our item struct we want to store in queue.
*/
struct user_s {
int age;
char* name;
QUEUE node;
};
int main() {
/**
* This will be our user pointer.
* It will point to the user we received from the queue.
*/
struct user_s* user;
/**
* John is 44.
*/
struct user_s john;
john.name = "john";
john.age = 44;
/**
* Henry is 32.
*/
struct user_s henry;
henry.name = "henry";
henry.age = 32;
/**
* Willy is 99.
*/
struct user_s willy;
willy.name = "willy";
willy.age = 99;
/**
* Initialize the queue of each user.
*/
QUEUE_INIT(&queue);
QUEUE_INIT(&john.node);
QUEUE_INIT(&henry.node);
QUEUE_INIT(&willy.node);
/* hgb, why need this line ?
((*(&queue))[0]) = john.node;
*/
printf(" sizeof(QUEUE)=%d \n", (int)(sizeof(QUEUE)) );
(*(QUEUE **) &((*(&queue))[0])) = &john.node;
/**
* Lets insert each user to the tail of the list.
*/
QUEUE_INSERT_TAIL(&queue, &john.node);
QUEUE_INSERT_TAIL(&queue, &henry.node);
QUEUE_INSERT_TAIL(&queue, &willy.node);
/**
* Retrieve a pointer to our first user john.
*/
q = QUEUE_HEAD(&queue);
printf("&queue=%p, queue[0]=%p, &q=%p \n", &queue, queue[0], q);
//q = ((*(&queue))[0]) ;
/**
* Should retrieve the user behind the "q" pointer.
*/
user = QUEUE_DATA(q, struct user_s, node);
/**
* Should output the name of john.
*/
printf("Received first inserted user: %s who is %d.\n",
user->name, user->age);
/**
* Now lets remove john from the queue.
*/
QUEUE_REMOVE(q);
printf("&queue=%p, queue[0]=%p \n", &queue, queue[0] );
/**
* Lets output the other two users through a for each loop.
*/
QUEUE_FOREACH(q, &queue) {
printf(" &q = %p, ", q);
user = QUEUE_DATA(q, struct user_s, node);
printf("Received rest inserted users: %s who is %d.\n",
user->name, user->age);
}
return 0;
}

浙公网安备 33010602011771号