2013-07-04 2 views
0

У меня вопрос о добавлении и добавлении новых элементов в отдельный список на 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: Исправлен код для большей ясности.

+0

'if (node ​​* newElement = malloc (sizeof (node))! = NULL)' - это не должно компилироваться. – Nobilis

+0

Упс, спасибо за головы, Nobilis. – herensuge

ответ

0

Вашей структура плохо определена:

typedef struct { 
    struct node* next; 
    int data; 
} node; 

Вторая строка объявляет next как указатель на неизвестную структуру с именем node. Это неизвестно, потому что вы еще не объявили об этом. Измените struct node* next на struct junk* next, и компиляция даст тот же результат. Компилятор может продолжаться и дальше, потому что ему не нужно знать, насколько велик «узел», все, что ему нужно, это знать, что это указатель.

Это нормально, чтобы определить, что такие вещи, как:

struct node { 
    struct node* next; 
    int data; 
}; 
typedef struct node node; 

Это работает, потому что к тому времени, когда компилятор приходит, чтобы сделать задание вы ссылаетесь, он знает, что такое struct node есть. В вашей версии вы никогда не определяете, что такое struct node. Обратите внимание, что я использовал одно и то же имя в typedef, как в struct, а именно «node». Это нормально, потому что typedefs и structs являются разными пространствами имен (и, следовательно, могут перекрываться).

0

Заявленная структура, подобная следующей, прекрасна.

#include<stdio.h> 
typedef struct node 
{ 
    int data; 
    struct node *next; 
}node; 

int main() 
{ 
    node n1, *pn1, *pn2; 
    pn1 = &n1; 
    pn2 = (node *)malloc(sizeof(node)); 
    pn1->data = 1; 
    pn1->next = NULL; 
    pn2->data = 2; 
    pn2->next = pn1; 
    printf("%d\n", pn2->data); 
    printf("%d\n", pn2->next->data); 
    return 0; 
} 

Я тестирую его в компиляторе MS cl, и он отлично работает. Вы можете быть свободны от указателя каста.

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

  • Нет связанных вопросов^_^