C Struct typedef和声明导致指针错误

时间:2016-10-13 15:14:09

标签: c pointers gcc struct

我尽可能多地尝试并提炼以下代码:

#include <stdlib.h>

typedef struct item{
    struct item *next;
}item;

void addItem(item *list)
{
    item *newItem = list;
    while(newItem->next != NULL){
        newItem = newItem->next;
    }

    newItem->next = malloc(sizeof(item));
    newItem->next->next = NULL;
}

int main()
{
    item *groceryList = NULL;
    groceryList = malloc(sizeof(item));
    if(groceryList == NULL)
        return 1;
    groceryList->next = NULL;

    addItem(groceryList);

    return 0;
}

编译好。但是将结构声明更改为(或更改的任意组合):

typedef struct{ /*Removed "item"*/
    item *next; /*Removed "struct"*/
}item;

编译时导致以下错误:

  

structpointertest.c:11:11:警告:从不兼容的指针类型中分配   structpointertest.c:15:15:错误:请求成员'next'的东西不是结构或联合

我不明白struct声明中导致此问题的原因是什么?它与我使用嵌套结构的事实有关吗?

感谢。

1 个答案:

答案 0 :(得分:3)

在C中,您必须在使用之前声明事物。当你这样做

typedef struct item { ... }

struct item部分是一个声明,告诉编译器存在结构名item。这意味着您可以在以后使用它,甚至在结构内部来定义指向自身的指针。

当你这样做时

typedef struct { ... } item;

你没有给结构命名,并且在结构之后声明了类型别名item,所以它不能在结构中使用。

简单的解决方案是使用第一种方式。另一种解决方案是在结构之前声明类型别名,例如

typedef struct item item;
struct item
{
    item *next;  // Can use type-alias, as it has been declared up above
};

无论哪种方式,你仍然必须给结构本身一个名字。

另请注意,struct item *next;(或item *next;)声明了一个成员变量,它是结构的指针,它不是递归嵌套的实际结构本身。创建指向尚未完全定义的东西的指针是可以的。