Ahdm
Ahdm

Reputation: 1

Incompatible pointer types when declaring a struct

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;
Code:
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;
}

How can this problem be solved?

Upvotes: -1

Views: 93

Answers (4)

Vlad from Moscow
Vlad from Moscow

Reputation: 311078

In this typedef declaration

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

there are declared two different type specifiers. The first one is the unnamed structure of complete type alias of which is numbers. The second one is the incomplete structure type struct numbers. That is there are two type specifiers numbers and struct numbers. They are different types and as a result are incompatible and hence pointers to objects of these types are also incompatible.

You need to introduce a structure tag as for example

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

or

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

There is one more problem with your function. The format string in this call of scanf

scanf("%c",&answer);

should have a leading space like

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

It allows to skip white space characters. Otherwise your call of scanf will also read for example the new line character '\n' that is placed in the buffer after pressing the Enter key in the preceding call of scanf

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

Also you need to check whether memory was successfully allocated in calls of malloc.

Pay attention to that the function should do only one task. This do-while loop

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

should be moved from the function in main. That is you need to write a function that appends only one node to the list and will be called from a loop similar to shown above.

Upvotes: 2

Madagascar
Madagascar

Reputation: 7345

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

Let's break these into two separate operations:

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

// And now the typedef.

Do you see the missing tag? struct numbers was never defined. It should be:

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

And now you can define an alias for struct numbers:

typedef struct numbers numbers;

Or do it like you were originally trying to:

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

Upvotes: 2

Tom Karzes
Tom Karzes

Reputation: 24062

You never defined struct numbers, so when it sees it, it assumes it's some distinct type from the numbers type. You can fix it by adding the missing tag to the typedef:

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

If you'd rather use numbers inside the structure as well, you can instead do:

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

This is a fairly common idiom.

Upvotes: 3

Eric Postpischil
Eric Postpischil

Reputation: 223663

First you give the structure a tag:

struct numbers

Then you define the structure using that tag:

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

Then you give the structure type a name:

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

In your original code, where you have struct numbers *NextNum;, there is no declaration of the tag numbers yet. So the compiler takes struct numbers to refer to some type it does not yet have a definition for.

The code typedef struct{ starts the definition of a structure type with no tag. The code struct numbers will never refer to this structure type, because a structure type with no tag and a structure type with a tag will never be the same type.

The code typedef struct{…}numbers; gives the structure type a name, numbers. But a name is not a tag. The name numbers by itself will refer to the structure type, but it refers to the structure with no tag. It does not refer to the structure type with a tag, struct numbers. numbers and struct numbers are different types. (This is different from C++, where structure, union, and class tags are automatically names of the types.)

In linked = linked->NextNum;, linked->NextNum is a pointer to struct numbers, but linked is a pointer to numbers. Since these are different types, and the assignment between them is inappropriate, the compiler warns you. Changing the structure definition as shown above will resolve this.

Upvotes: 3

Related Questions