У меня вопрос о добавлении и добавлении новых элементов в отдельный список на C. Я провел некоторое исследование, прежде чем решила спросить, и нашел ответы на вопрос similar question, который в какой-то мере разрешите мое сомнение, но я до сих пор не совсем понял, почему некоторые кастинги необходимы, чтобы угодить компилятору.Внедрение новых элементов для добавления их в отдельный список
Я использую GCC в Ubuntu 12.04 LTS:
$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
Так я осуществил следующий код:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 typedef struct {
5 struct node* next;
6 int data;
7 } node;
8
9 node* appendElement(node* head, int data);
10 node* removeElement(node* head, int data);
11
12 int main(int argc, char** args){
13 //main code
14 return 0;
15 }
16
17 node* appendElement(node* head, int data){
18 node* newElement;
19 if(head == NULL){
20 if((newElement = malloc(sizeof(node))) != NULL){
21 newElement->data = data;
22 newElement->next = NULL;
23 return newElement;
24 }
25 else{
26 fprintf(stderr, "Error");
27 return NULL;
28 }
29 }
30 else{
31 node* n = head;
32 while(n->next != NULL){
33 n = (node*)n->next;
34 }
35 if((newElement = malloc(sizeof(node))) != NULL){
36 newElement->data = data;
37 newElement->next = NULL;
38 n->next = (void*)newElement;
39 return head;
40 }
41 else{
42 fprintf(stderr, "Error");
43 return NULL;
44 }
45 }
46 }
47
48 node* removeElement(node* head, int data){
49 node* aux;
50 if(head == NULL){
51 printf("Empty list, nothing to remove.\n");
52 return NULL;
53 }
54 else if(head->data == data){
55 aux = (node*)head->next;
56 free(head);
57 return aux;
58 }
59 else{
60 node* n = head;
61 while(n->next != NULL){
62 aux = (node*)n->next;
63 if(aux->data == data){
64 n->next = aux->next;
65 free(aux);
66 return head;
67 }
68 n = (node*)n->next;
69 }
70 printf("Can't find %d in list.\n", data);
71 return head;
72 }
73 }
Из ответов я прочитал один может измениться:
4 typedef struct {
5 struct node* next;
6 int data;
7 } node;
в:
4 typedef struct _node {
5 struct _node* next;
6 int data;
7 } node;
для того, чтобы избежать явного приведения в следующих строках:
33 n = (node*)n->next;
38 n->next = (void*)newElement;
62 aux = (node*)n->next;
68 n = (node*)n->next;
Как и следовало ожидать, это работает. Я понимаю, что компилятор «не любит» работать с неопределенными структурами. (А также, что аргумент malloc
может быть newElement
.)
Мой вопрос: что, если вы не хотите изменять декларацию структуры? Почему эти кастинги необходимы, чтобы сделать компилятор счастливым? Я считаю, что даже без этих кастингов программа по-прежнему работает.
В частности, литье в void*
Мне пришлось реализовать в строке 38, не убеждая меня вообще. Я знаю, что void*
является общим указателем, и поэтому каждый указатель может быть опущен без проблем, поэтому я использовал его.
Возможно, мое понимание декларации структуры и typedef
не так хорошо, как я думал. Спасибо за ваше время.
EDIT: Исправлен код для большей ясности.
'if (node * newElement = malloc (sizeof (node))! = NULL)' - это не должно компилироваться. – Nobilis
Упс, спасибо за головы, Nobilis. – herensuge