#include <stdio.h>
#ifdef QUEUE_MACRO_DEBUG
/* Store the last 2 places the queue element or head was altered */
struct qm_trace {
char * lastfile;
int lastline;
char * prevfile;
int prevline;
};
#define TRACEBUF struct qm_trace trace;
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_TRACE_HEAD(head) do { \
(head)->trace.prevline = (head)->trace.lastline; \
(head)->trace.prevfile = (head)->trace.lastfile; \
(head)->trace.lastline = __LINE__; \
(head)->trace.lastfile = __FILE__; \
} while (0)
#define QMD_TRACE_ELEM(elem) do { \
(elem)->trace.prevline = (elem)->trace.lastline; \
(elem)->trace.prevfile = (elem)->trace.lastfile; \
(elem)->trace.lastline = __LINE__; \
(elem)->trace.lastfile = __FILE__; \
} while (0)
#else
#define QMD_TRACE_ELEM(elem)
#define QMD_TRACE_HEAD(head)
#define TRACEBUF
#define TRASHIT(x)
#endif /* QUEUE_MACRO_DEBUG */
/*
* Horrible macros to enable use of code that was meant to be C-specific
* (and which push struct onto type) in C++; without these, C++ code
* that uses these macros in the context of a class will blow up
* due to "struct" being preprended to "type" by the macros, causing
* inconsistent use of tags.
*
* This approach is necessary because these are macros; we have to use
* these on a per-macro basis (because the queues are implemented as
* macros, disabling this warning in the scope of the header file is
* insufficient), whuch means we can't use #pragma, and have to use
* _Pragma. We only need to use these for the queue macros that
* prepend "struct" to "type" and will cause C++ to blow up.
*/
#if defined(__clang__) && defined(__cplusplus)
#define __MISMATCH_TAGS_PUSH \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wmismatched-tags\"")
#define __MISMATCH_TAGS_POP \
_Pragma("clang diagnostic pop")
#else
#define __MISMATCH_TAGS_PUSH
#define __MISMATCH_TAGS_POP
#endif
/*
* Singly-linked List declarations.
*/
#define SLIST_HEAD(name, type) \
__MISMATCH_TAGS_PUSH \
struct name { \
struct type *slh_first; /* first element */ \
} \
__MISMATCH_TAGS_POP
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
__MISMATCH_TAGS_PUSH \
struct { \
struct type *sle_next; /* next element */ \
} \
__MISMATCH_TAGS_POP
/*
* Singly-linked List functions.
*/
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST((head)); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != NULL; \
(varp) = &SLIST_NEXT((var), field))
#define SLIST_INIT(head) do { \
SLIST_FIRST((head)) = NULL; \
} while (0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
} while (0)
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) \
__MISMATCH_TAGS_PUSH \
do { \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = SLIST_FIRST((head)); \
while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_REMOVE_AFTER(curelm, field); \
} \
TRASHIT((elm)->field.sle_next); \
} while (0) \
__MISMATCH_TAGS_POP
#define SLIST_REMOVE_AFTER(elm, field) do { \
SLIST_NEXT(elm, field) = \
SLIST_NEXT(SLIST_NEXT(elm, field), field); \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
struct Data
{
SLIST_ENTRY(Data) next;
int m_iData;
//other object..
};
//利用宏SLIST_HEAD定义一个表头
SLIST_HEAD(myHead, Data);
static struct myHead listHead;
int main(void)
{
struct Data *pIndex = NULL;
struct Data *pIndex_tmp = NULL;
struct Data **pIndex_tmp1 = NULL;
struct Data listDataElm1 = { NULL, 1 };
struct Data listDataElm2 = { NULL, 2 };
struct Data listDataElm3 = { NULL, 3 };
struct Data listDataElm4 = { NULL, 4 };
struct Data listDataElm5 = { NULL, 5 };
//利用宏SLIST_INIT初始化表头
SLIST_INIT(&listHead);
//利用宏SLIST_EMPTY来判断一个链表是否为空
if (SLIST_EMPTY(&listHead))
printf("this Singly-linked List is null!\r\n");
//利用宏SLIST_INSERT_HEAD向表头插入一个对象
SLIST_INSERT_HEAD(&listHead, &listDataElm1, next);
//利用宏SLIST_INSERT_AFTER向链表的尾部添加对象
SLIST_INSERT_AFTER(&listDataElm1, &listDataElm2, next);
SLIST_INSERT_AFTER(&listDataElm2, &listDataElm3, next);
SLIST_INSERT_AFTER(&listDataElm3, &listDataElm4, next);
SLIST_INSERT_AFTER(&listDataElm4, &listDataElm5, next);
SLIST_FOREACH(pIndex, &listHead, next)
{
if (pIndex != NULL){
printf("SLIST_FOREACH pIndex->m_iData = %d\r\n", pIndex->m_iData);
}
}
// 多遍历到前一个数据
SLIST_FOREACH_PREVPTR(pIndex, pIndex_tmp1, &listHead, next){
if (pIndex != NULL){
printf("SLIST_FOREACH_PREVPTR pIndex->m_iData = %d\r\n", pIndex->m_iData);
}
}
SLIST_FOREACH_SAFE(pIndex, &listHead, next, pIndex_tmp)
{
if (pIndex != NULL){
printf("SLIST_FOREACH_SAFE pIndex->m_iData = %d\r\n", pIndex->m_iData);
}
}
// 链表头删
SLIST_REMOVE_HEAD(&listHead, next);
SLIST_FOREACH_SAFE(pIndex, &listHead, next, pIndex_tmp)
{
if (pIndex != NULL){
printf("SLIST_REMOVE_HEAD pIndex->m_iData = %d\r\n", pIndex->m_iData);
}
}
// 链表尾删
SLIST_REMOVE_AFTER(&listDataElm4, next);
SLIST_FOREACH_SAFE(pIndex, &listHead, next, pIndex_tmp)
{
if (pIndex != NULL){
printf("SLIST_REMOVE_AFTER pIndex->m_iData = %d\r\n", pIndex->m_iData);
}
}
// 删除链表指定位置数据
SLIST_REMOVE(&listHead, &listDataElm3, Data, next);
SLIST_FOREACH_SAFE(pIndex, &listHead, next, pIndex_tmp)
{
if (pIndex != NULL){
printf("SLIST_REMOVE pIndex->m_iData = %d\r\n", pIndex->m_iData);
}
}
return 0;
}