2016-06-02 10 views
0

Может ли кто-нибудь помочь мне понять указатели void с помощью связанного списка.Создание связанного списка более общий

у меня есть:

struct listNode 
{ 
    int nodeValue; 
    struct listNode * next; 
}; 

typedef struct listNode listNode; 

, который работает только с Интс. Если я изменил int nodeValue на void * nodeValue, как бы мне отправить значения в мой связанный список, используя указатель void?

Например, я имел надстройку к передней функции:

void addFront(listNode *L, int number); 

который принимает listNode и номер.

Если это была пустота * указатель, я бы просто изменить подпись:

void addFront(listNode *L, void* value); 

В моих основных функций с помощью Интс у меня есть что-то вроде:

int main(void) 
{ 
    listNode *list; 
    list = createList(); 

    for (int x = 0;x < 8;x++) 
    { 
     addFront(list,x); 

    } 

    return(0); 
} 

где createList определяется как :

listNode *createList() 
{ 
    listNode *anyNode; 
    anyNode = malloc(sizeof(listNode)); 
    anyNode->next = NULL; 
    return anyNode; 
} 

listNode *initNode(int number) 
{ 
    listNode *newNode; 
    newNode = malloc(sizeof(listNode)); 
    newNode->nodeValue = number; 
    newNode->next = NULL; 
    return(newNode); 
} 

Чтобы сделать список более универсальным, как я могу передавать целые числа, используя void * вместо объявляя целое число.

ответ

1

К сожалению, этот вид родового поведения идет по цене больших накладных расходов: для того, чтобы сохранить int в списке вы должны расширить свою сферу путем выделения в int динамически:

listNode *initNode(int number) 
{ 
    listNode *newNode; 
    newNode = malloc(sizeof(listNode)); 
    newNode->nodeValue = malloc(sizeof(int)); 
    *(newNode->nodeValue) = number; 
    newNode->next = NULL; 
    return(newNode); 
} 

Это увеличивает много раз, поскольку malloc(sizeof(int)); обычно выделяет как минимум 16-байтовый блок.

-1

Альтернативное решение использует массив 0-го размера в объявлении listNode. Например:

#include <stdlib.h> 
#include <string.h> 

struct listNode 
{ 
    struct listNode *next; 
    int nodeValue[0]; 
}; 

struct listNode *addFront(struct listNode **head, void *data, size_t size) 
{ 
    struct listNode *new_node = calloc(sizeof(struct listNode) + size, 1); 
    if(!new_node) 
    return NULL; 
    new_node->next = *head; 
    *head = new_node->next; 
    memcpy(new_node->nodeValue, data, size); 
} 

void addInt2Front(struct listNode **head, int value) 
{ 
    addFront(head, &value, sizeof(value)); 
} 

int main(void) 
{ 
    struct listNode *head = NULL; 
    addInt2Front(&head, 5); 
} 

Это уменьшает накладные расходы из двух распределений, поскольку память для nodeValue выделяет с listNode блока по одному calloc (вызов).

+0

Извините, мне нужно добавить new_node. Я забыл написать его в код. –

0

Один из способов хранения либо ints или указателей - это сделать nodeValue в тип объединения. Обратите внимание: во избежание неопределенного поведения код вызова должен быть согласованным (т. Е. Если вы добавите int в связанный список, вы не должны пытаться позже обращаться к ним как указатели или наоборот).

union intOrPointer 
{ 
    int intValue; 
    void * pointerValue; 
}; 

struct listNode 
{ 
    union intOrPointer nodeValue; 
    struct listNode * next; 
}; 

typedef struct listNode listNode; 

listNode *initNode(int number) 
{ 
    listNode *newNode; 
    newNode = malloc(sizeof(listNode)); 
    newNode->nodeValue.intValue = number; 
    newNode->next = NULL; 
    return(newNode); 
} 
Смежные вопросы