LINUX.ORG.RU

Двусвязные списки в СИ

 ,


1

1

Всем привет)

Написал пробник двусвязного списка -> https://github.com/maksspace/mylist/tree/master

Прошу совет: можно ли использовать подобное в реальном проекте? или лучше стандартный вид когда есть дескриптор списка и ноды и т.п?



Последнее исправление: cetjs2 (всего исправлений: 2)
Ответ на: комментарий от SZT

Да не, это как раз-таки показывает твою тотальную балаболимстость. Ты толкаешь про то, что проблема макроса в том, что он 100% встаивается, а после выкатываешь инлайн, который так же 100% встраивается. И тут уже только один вопрос - человек здоров?

anonymous
()
Ответ на: комментарий от SZT

Но в цикле тебе и компилятор может функцию встроить.

Из «другой единицы трансляции»?

А если макрос вызывается из кучи мест, он во все эти места будет встраиваться.

Это прекрасно. Длю бой программы самое лучшее - чего она может добиться - это отсутствие вызовов как таковых. Инлайн и анрол - это два столпа на которых стоит производительность в текущем мире.

Если макрос большой и вызывается много раз, это может быть критичным.

Не может. Вызваться много раз он может только из одно места. Другого не бывает. Не существует такого юзкейса.

К тому же я уже сказал, на макрос нельзя передать указатель т.к. он не функция.

Зачем передавать указатель на макрос?

Ах да, удачи передать инлайн-функцию. Эксперты - они такие.

anonymous
()
Ответ на: комментарий от anonymous

Если ТС использует их там, где можно заюзать функцию - он дурак.

А как еще можно так типы динамически генерить? в функцию то тип не передаш. Я сделал все что можно было на функциях, а все остальное на макросах:

http://melpon.org/wandbox/permlink/ATgqV1phRWjWK48G

maksspaces
() автор топика
Ответ на: комментарий от maksspaces

А как еще можно так типы динамически генерить?

А причём тут типы? Причину для одного ты нашел - причины для остальных нет.

Я сделал все что можно было на функциях, а все остальное на макросах:

Дерьмо убогое.

size_t

Что это за дерьмо?

#define LIST_NODE(type) \
    struct {            \
        size_t//<<вот это next;    \//и это
        size_t prev;    \//вот это
        type data;      \
    }//что это за дерьмо?
        PREV_NODE_PTR(next_node) = new_node;
        NEXT_NODE_PTR(new_node)  = next_node;
        PREV_NODE_PTR(new_node)  = prev_node;
        NEXT_NODE_PTR(prev_node) = new_node;//что это за дерьмо?

Идея дерьмо - исполнение дерьмо.

#define LIST_NODE_TYPE_NEW(type, name) typedef struct name {\
  struct name * prev, * next;\
  type data;\
} name ## _t;

void * list_prepend(void * node, void * head) {
  typedef struct {void * prev, * next;} node_t;
  *(node_t *)node = (node_t){NULL, head};
  return ((node_t *)head)->prev = node;
}

Зачем вообще это дерьмо городить, если достаточно сказать, что должно быть 2первых филда твоих? Либо просто сделать макрос «втавь его в начала своей структуры».

Оно бесполезно, ибо нахрен никому не нужен список на одно поле. Или мне как дауну юзать node->data.hernya? Зачем?

Но хотя бы лучше того, что было тут изначально - мне даже лень было то убожество комментировать.

Код должен быть минималистичным и красивым, а не убогим дерьмом вгоняющим в уныние своей убогостью.

list_node_new(sizeof(node_int), malloc);

Дерьмо.

node_int* tmp = malloc(sizeof(node_int));

Г - гениальность. П - повторяемость для слабаков.

LIST_NODE_VAL(node_int, current)->data

Б - больше макросов. Нахрен ты вообще свою структуру туда впихивал, чтобы потом поле через какое-то дерьмо неведомое получать? Зачем?

А за обход списка фором - за такое отправляют сортиры драить.

Тотальное отсутствие логики как таковой в паре с таким отсутствием понимания происходящего вообще. Ты же должен осознанно что-то впихивать, а не форфан, не? Да и я уже 10раз говорил - обобщенные интерфейсы на сишки пишут только больные на головку, ибо а) они не нужны, б) они всё ровно будут убогими.

Единственный обобщенный интерфейс в сишке - это void * и сырая память.

anonymous
()
Ответ на: комментарий от anonymous

А за обход списка фором - за такое отправляют сортиры драить.

Почему не фором? В linux/list.h для обхода тоже for используется

#include <stdio.h>
#include <stdlib.h>

#define NODE_LINK_TYPE typedef struct { void *prev, *next; }

void* list_prepend(void* node, void* head) {
    NODE_LINK_TYPE node_link_t;
    *(node_link_t*)node = (node_link_t){NULL, head};
    return ((node_link_t*)head)->prev = node;
}

void* list_append(void* tail, void* node) {
    NODE_LINK_TYPE node_link_t;
    *(node_link_t*)node = (node_link_t){tail, NULL};
    return ((node_link_t*)tail)->next = node;
}

void* list_insert(void* new, void* prev, void* next) {
    NODE_LINK_TYPE node_link_t;
    *(node_link_t*)new = (node_link_t){prev, next};
    return ((node_link_t*)prev)->next = ((node_link_t*)next)->prev = new;
}

#define list_foreach(head, current) \
    for(typeof(head) current = head; current != NULL; current = current->next)

/* Each node of the list must contain:
 * struct node_name *prev, *next;
 * at the beginning */

typedef struct node {
    struct node *prev, *next;
    int foo;
    char bar;
} node_t;

int main(int argc, char *argv[])
{
    node_t n1;
    n1.foo = 16;
    
    node_t n2;
    n2.foo = 32;
    
    node_t n3;
    n3.foo = 64;
    
    list_append(&n1, &n2);
    list_insert(&n3, &n1, &n2);
    
    list_foreach(&n1, current) {
        printf("%d\n", current->foo);
    }
    
    return 0;
}


maksspaces
() автор топика

И кстати о списках и кеше. Простенький бенчмарк показывает, что разница между скоростью обхода массива и односвязного списка, если список компактифицирован, составляет всего 15 раз. При увеличении среднего расстояния между элементами списка разница быстро растет до 600 раз, с резким скачком на границе cache line. Кто тут пищал про нерелевантность архитектуры иерархии памяти?

anonymous
()
Ответ на: комментарий от anonymous

Ну если Xeon E5 говеный, то я уж не знаю что не говеное. POWER8?

anonymous
()
Ответ на: комментарий от maksspaces

Обойдешься, сам напиши. Чужим бенчмаркам все равно никто не верит. Еще лучше будет, если ты напишешь такой, где будет разница в менее чем 15 раз.

anonymous
()
Ответ на: комментарий от anonymous

Да действительно. У меня время обхода 10 000 000 массива чуть больше чем в 7 раз быстрее чем обход списка такой же длинны.

maksspaces
() автор топика
Ответ на: комментарий от anonymous

Ты очищаешь кеш между итерациями?

Смешно. Иди ещё из под регистранта поудаляй. Это же надо быть настолько ничтожным, чтобы ссаться под своей учёткой что-то кукарекать, а как обоссут - заходить и выпиливать.

anonymous
()
Ответ на: комментарий от anonymous

Слив засчитан.

Чужим бенчмаркам все равно никто не верит.

В отличии от тебя, ламерка, мне не нужно во что-либо верить или не верить.

Еще лучше будет, если ты напишешь такой, где будет разница в менее чем 15 раз.

Я итак знаю сколько там будет разница - я не настолько нулёвый, что мне для этого нужен бенчмарк. Ты кукарекнул - выкатывай. Особенно про кешлайн интересно.

Чтож вы все ссыкливые такие? Балабольство оно такое.

Ламерюжка такая смешная.

anonymous
()
Ответ на: комментарий от mix_mix

Да с самого начала ясно было, что царь не настоящий. Настоящий, наверное, в запое.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.