2013-07-04 42 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不如我想象的那么好。谢谢你的时间。

编辑:更正了一些代码更清晰。

+0

'if(node * newElement = malloc(sizeof(node))!= NULL)' - 这不应该编译。 – Nobilis

+0

哎呀,谢谢你的抬头,诺比利斯。 – 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中使用了与结构中相同的名称,即'node'。这是可以的,因为typedefs和struct是不同的名称空间(因此可以重叠)。

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编译器,它工作正常。你可以免费使用指针。

相关问题