2016-07-04 4 views
1

Я начинаю эксперимент C со связанными списками, и я нашел репозиторий Github для одного. функция создания записывается так:Использование функции с аргументом указателя void

Node* ListCreate(void* data) { 
    Node *head = malloc(sizeof(Node)); 
    if (head != NULL) { 
     head->next = NULL; 
     head->data = data; 
    } 
    return head; 
} 

Я был в состоянии использовать его, изменяя void* к int, а затем в main делать:

Node *root = ListCreate(5); 

Но потом я прочитал немного о недействительных указателях и похоже, они могут использоваться в качестве типичных типов вроде подобных C++-шаблонов, что было бы полезно, если бы я мог понять, как они работают. Я попробовал несколько вещей, и ближе всего я должен не получать его работу без ошибок, но одно предупреждение:

incompatible integer to pointer conversion passing 'int' to parameter of type 'void *'

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

+1

Вы можете использовать указатели void, когда одна функция будет обрабатывать различные типы данных (и особенно когда имеет смысл передавать указатели на эти разные типы данных), но когда она будет обрабатывать один тип, вы обычно пытаетесь чтобы избежать этого. Обратите внимание, что такие функции, как 'qsort()' или 'bsearch()' пропускают указатели void вокруг, поэтому, если вы их используете, у вас будут функции, которые принимают указатели void, но преобразуют переданный указатель в правильный (ожидаемый) тип. Вы не можете преобразовать из целых типов в указатели без явного приведения; вы не можете конвертировать из типов с плавающей точкой вообще. –

+1

Я пытался сделать так, чтобы данные связанного списка могли быть настроены на ints, floats или chars. Это гораздо сложнее сделать на C, чем на C++? – Austin

+1

OK; Каков тип данных в списке? Вы сохраняете значения «int» или «int *»?Обработка 'int *' достаточно проста в коде списка, но сложнее в коде с использованием кода списка. У вас должна быть отдельная переменная 'int' для каждого указателя, чтобы указать, чтобы вы могли сохранить их в списке (и есть пространство теряется, потому что у вас есть указатель и значение, на которое он указывает). То же самое для 'float'. Когда вы говорите 'char', вы имеете в виду одиночные символы (жесткие) или строки (aka' char * ', относительно легко)? –

ответ

0

Я думаю, что существует необходимость обертывания для числовых литералов (или литых?).
Как это:

void *BOX_VAR;//Not require if use GCC extension 
#define BOX(type, value) ((*(type *)(BOX_VAR=malloc(sizeof(type))) = value), BOX_VAR) 
#define UNBOX(type, value) (*(type *)(value)) 

Node *list = ListCreate(BOX(int, 5)); 
int v = UNBOX(int, list->data); 
printf("%d\n", v); 
1

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

Но если вы хотите использовать то же определение функции, то использование может передать указатель данных (int или char) и ввергнут их в void *.

/* main: start */ 
int main(void) 
{ 
    Node *list_head; /* Points to first element in list */ 
    Node *node_tmp; /* Just a temporary pointer */ 

    int *pint; 
    char *pchar; 

    /* create an empty list */ 
    list_head = NULL; 

    /* Note that there is no error checking done for 
    * malloc, which is not good 
    */ 

    /* Create a node which points to int */ 
    pint = malloc(sizeof(int)); 
    *pint = 10; 
    node_tmp = ListCreate((void *) pint); 
    /* Add this node to list */ 
    list_head = add(node_tmp, list_head); 

    /* Create a node which points to char */ 
    pchar = malloc(sizeof(char)); 
    *pchar = 'c'; 
    node_tmp = ListCreate((void *) pchar); 
    /* Add this node to list */ 
    list_head = add(node_tmp, list_head); 

    /* print total number of nodes in list */ 
    print_tot_nodes(list_head); 
    return 0; 
} 

Код для add и print_tot_nodes являются для опущен краткости.

Обратите внимание, что функции, такие как print_tot_nodes или add, не будут иметь проблем, если data указывает на разные типы данных. Но если вам нужно реализовать функцию типа Node *smallest(Node *head), которая возвращает указатель на узел с наименьшим элементом, тогда это может усложниться.

Таким образом, проще использовать другой список для разных типов. Однако вы можете cast фактический указатель на некоторый тип данных до void *, если вам нужно использовать то же определение функции, что и в исходном посте.

Смежные вопросы