声明结构时不兼容的指针类型

问题描述 投票:0回答:4
list.h: In function ‘CreateNewLinks’:
list.h:29:20: warning: assignment to ‘numbers *’ from incompatible pointer type ‘struct numbers *’ [-Wincompatible-pointer-types]
   29 |             linked = linked->NextNum;
代码:
typedef struct{
    int num;
    struct numbers *NextNum;
}numbers;


numbers *CreateNewLinks(){

    numbers *head=NULL;
    
    head=malloc(sizeof(numbers));
    numbers* linked = head;
    
    char answer;
    
    do{
    
        printf("Enter number : ");
        scanf("%d",&linked->num);
        
        printf("Do you want to add (y/n) : ");
        scanf("%c",&answer);
        
        if(answer == 'y' || answer == 'Y'){
            linked->NextNum = malloc(sizeof(numbers));
            linked = linked->NextNum;
        }else
           linked->NextNum = NULL;
    
    }while(answer =='y' || answer == 'Y');
    
    return head;
}

这个问题如何解决?

c
4个回答
2
投票

首先给结构一个标签:

struct numbers

然后使用该标签定义结构:

struct numbers {
    int num;
    struct numbers *NextNum;
};

然后为结构类型命名:

typedef struct numbers {
    int num;
    struct numbers *NextNum;
} numbers;

在您的原始代码中,您有

struct numbers *NextNum;
,但还没有标签
numbers
的声明。因此编译器使用
struct numbers
来引用某些尚未定义的类型。

代码

typedef struct{
开始定义没有标签的结构类型。代码
struct numbers
永远不会引用这个结构类型,因为没有标签的结构类型和有标签的结构类型永远不会是相同的类型。

代码

typedef struct{…}numbers;
为结构类型提供了一个名称,
numbers
。但名称不是标签。名称
numbers
本身指的是结构类型,但它指的是没有标签的结构。它不是指带有标签
struct numbers
的结构类型。
numbers
struct numbers
是不同的类型。 (这与 C++ 不同,在 C++ 中,结构、联合和类标签自动成为类型的名称。)

linked = linked->NextNum;
中,
linked->NextNum
是指向
struct numbers
的指针,但
linked
是指向
numbers
的指针。由于它们是不同的类型,并且它们之间的赋值不合适,因此编译器会警告您。如上所示更改结构定义将解决此问题。


2
投票

您从未定义过

struct numbers
,因此当它看到它时,它会假设它是与
numbers
类型不同的类型。您可以通过将缺少的标签添加到
typedef
:

来修复它
typedef struct numbers {
    int num;
    struct numbers *NextNum;
} numbers;

如果您也想在结构内部使用

numbers
,您可以这样做:

typedef struct numbers *numbers;
struct numbers {
    int num;
    numbers *NextNum;
};

这是一个相当常见的习语。


1
投票
typedef struct{
    int num;
    struct numbers *NextNum;
}numbers;

让我们将它们分成两个单独的操作:

struct {
    int num;
    struct numbers *NextNum;
};

// And now the typedef.

您看到丢失的标签了吗?

struct numbers
从未被定义。应该是:

struct numbers {
    int num;
    struct numbers *NextNum;
}

现在您可以为

struct numbers
定义别名:

typedef struct numbers numbers;

或者像你最初尝试的那样去做:

typedef struct numbers {
    int num;
    struct numbers *NextNum;
} numbers;

0
投票

在这个 typedef 声明中

typedef struct{
    int num;
    struct numbers *NextNum;
}numbers;

声明了两个不同的 tyoe 说明符。第一个是完整类型别名的未命名结构,其别名为

numbers
。第二种是不完全结构类型
struct numbers
。也就是说,有两个类型说明符
numbers
struct numbers
。它们是不同的类型,因此不兼容,因此指向这些类型的对象的指针也是不兼容的。

您需要引入一个结构标签,例如

typedef struct numbers{
    int num;
    struct numbers *NextNum;
}numbers;

typedef struct numbers numbers;
struct numbers{
    int num;
    numbers *NextNum;
};

您的函数还有一个问题。这次调用中的格式字符串

scanf

scanf("%c",&answer);

应该有一个前导空格,例如

scanf(" %c",&answer);
      ^^^  

它允许跳过空白字符。否则,您对

scanf
的调用也将读取例如在之前调用
'\n'
 中按 Enter 键后放置在缓冲区中的新行字符 
scanf

scanf("%d",&linked->num);

还需要检查

malloc
的调用中是否成功分配了内存。

注意函数应该只执行一项任务。这个 do-while 循环

do{
    printf("Enter number : ");
    scanf("%d",&linked->num);
    //...
}while(answer =='y' || answer == 'Y');

应从 main 中的函数中移出。也就是说,您需要编写一个函数,仅将一个节点附加到列表中,并且将从类似于上面所示的循环中调用。

© www.soinside.com 2019 - 2024. All rights reserved.