И так, после некоторых экспериментов я пришел к следующей реализации списков, которая включает в себя все лучшее из стандартной реализации и реализации «как в линуксе» :)
Достоинства: нигде не используются преобразования указателей, простая чистая реализация, работа идет сразу с лементами (как в стандартных списках) и не нужно вычислять адрес самой структуры данных (как в списках из линукса).
В настоящий момент в каждую сруктуру, которая может включаться в список нужно добавить служебный элемент для связи (макрос LIST_LINK), который всегда называется link. Если во все макросы добавить название служебного поля как параметр, то можно иметь один и то-же элемент в разных списках (как в линуксе), мне это не нужно, поэтому не делал.
Конструктивная критика приветствуется.
Сама реализация:
#ifndef _LIST_H_
#define _LIST_H_
#define LIST_LINK(type) \
  struct { struct type *next;  struct type *prev; } link
#define DECLARE_LIST(type, name) \
  type name = { .link = { .next = &(name), .prev = &(name) } }
#define LIST_INIT(ptr) \
  do { (ptr)->link.next = ptr; (ptr)->link.prev = ptr; } while (0)
#define list_add_after(_item, _new) \
  do { \
    (_new)->link.next = (_item)->link.next; \
    (_new)->link.prev = (_item); \
    (_item)->link.next->link.prev = (_new); \
    (_item)->link.next = (_new); \
  } while (0)
#define list_add_before(_item, _new) \
  do { \
    (_new)->link.next = (_item); \
    (_new)->link.prev = (_item)->link.prev; \
    (_item)->link.prev->link.next = (_new); \
    (_item)->link.prev = (_new); \
  } while (0)
#define list_add(_list, _new) \
  list_add_before(_list, _new)
#define list_add_head(_list, _new) \
  list_add_after(_list, _new)
#define list_del(_item) \
  do { \
    (_item)->link.prev->link.next = (_item)->link.next; \
    (_item)->link.next->link.prev = (_item)->link.prev; \
    (_item)->link.next = NULL; \
    (_item)->link.prev = NULL; \
  } while (0)
#define list_del_init(_list) \
  do { \
    list_del(_item); \
    LIST_INIT(_item); \
  } while (0)
#define list_is_empty(_list) \
  ((_list)->link.next == (_list))
#define list_foreach(_var, _list) \
  for (_var = (_list)->link.next; _var != (_list); _var = _var->link.next)
#define list_foreach_back(_var, _list) \
  for (_var = (_list)->link.prev; _var != (_list); _var = _var->link.prev)
#define list_foreach_var(_type, _var, _list) \
  for (_type *_var = (_list)->link.next; _var != (_list); _var = _var->link.next)
#define list_foreach_back_var(_type, _var, _list) \
  for (_type *_var = (_list)->link.prev; _var != (_list); _var = _var->link.prev)
#define list_foreach_safe(_var, _list, _tmp) \
  for (_var = (_list)->link.next, _tmp = (_var)->link.next; _var != (_list); \
       _var = _tmp, _tmp = (_var)->link.next)
#define list_foreach_back_safe(_var, _list, _tmp) \
  for (_var = (_list)->link.prev, _tmp = (_var)->link.prev; _var != (_list); \
       _var = _tmp, _tmp = (_var)->link.prev)
#endif // _LIST_H_
Пример использования:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
typedef struct num_t
{
  int      num;
  LIST_LINK(num_t);
} num_t;
static DECLARE_LIST(num_t, nums);
int main(void)
{
  num_t n1, n2, n3, n4;
  num_t *n5;
  num_t *ext_var;
  n1.num = 1111;
  n2.num = 2222;
  n3.num = 3333;
  n4.num = 4444;
  n5 = malloc(sizeof(num_t));
  n5->num = 5555;
  list_add(&nums, &n1);
  list_add(&nums, &n2);
  list_add(&nums, &n3);
  list_add(&nums, &n4);
  list_add(&nums, n5);
  list_del(&n2);
  printf("Go through list using c99 style for loop declaration:\n");
  list_foreach_var (num_t, var, &nums)
  {
    printf("  %d\n", var->num);
  }
  printf("Go through list using external variable as loop parameter:\n");
  list_foreach (ext_var, &nums)
  {
    printf("  %d\n", ext_var->num);
  }
  return 0;
}











