Getting error C: conversion to non-scalar type

Hi, I am getting this error:

error: conversion to non-scalar type requested 

Here are my structures:

 typedef struct value_t value; struct value{ void* x; int y; value* next; value* prev; }; typedef struct key_t key; struct key{ int x; value * values; key* next; key* prev; }; 

Here is the code that is causing me problems:

 struct key new_node = (struct key) calloc(1, sizeof(struct key)); struct key* curr_node = head; new_node.key = new_key; struct value head_value = (struct value) calloc(1, sizeof(struct value)) 

I do not intend to use calloc for structs? In addition, I have a structure that I created, and then I want to set it to a pointer to the same type of structure, but getting an error. This is an example of what I am doing:

 struct value x; struct value* y = *x; 

it gives me this error

 error: invalid type argument of 'unary *' 

When I do y = x, I get this warning:

 warning: assignment from incompatible pointer type 
+4
source share
6 answers

You are trying to assign a pointer expression (return type malloc () and friends void *) to type struct (struct new_node). This is nonsense. Also: cast is not required (and possibly dangerous, as it may hide errors)

 struct key *new_node = calloc(1, sizeof *new_node); 

same problem with another malloc () line:

 struct value *head_value = calloc(1, sizeof *head_value); 

Additional errors: you omit the keyword "struct" (which is allowed in C ++, but nonsense in C):

 struct key{ int x; struct value *values; struct key *next; struct key *prev; }; 

UPDATE: use of structures and pointers to struct.

 struct key the_struct; struct key other_struct; struct key *the_pointer; the_pointer = &other_struct; // a pointer should point to something the_struct.x = 42; the_pointer->x = the_struct.x; /* a->b can be seen as shorthand for (*a).b :: */ (*thepointer).x = the_struct.x; /* and for the pointer members :: */ the_struct.next = the_pointer; the_pointer->next = malloc (sizeof *the_pointer->next); 
+12
source

I do not think you understood typedef s correctly.

A common idiom using typedefs for naming convenience is this:

 struct foo { int something; }; typedef struct foo foo_t; 

Then you use the type foo_t instead of the less convenient struct foo .

For convenience, you can combine the declaration of the structure and typedef in one block:

 typedef struct { int something; } foo_t; 

This defines a foo_t in the same way as above.

The last token in the typedef line is the name you assign. I have no idea which code you wrote actually executes with your namespace, but I doubt what you want.

Now, with regard to the code itself: calloc returns a pointer, which means your listing, and your storage type should be struct key* (or, if you correct your name, key_t ). The correct line is struct key* new_node = (struct key*)calloc(1, sizeof(struct key));

For your second, independent, graduation, the last line should be struct value* y = &x; . You want y keep the address x , not the thing at address x. This error message indicates this: you are abusing the unary star operator to try to dereference a variable other than a pointer.

+3
source
 struct key new_node = (struct key) calloc(1, sizeof(struct key)); 

calloc returns the value of the pointer ( void * ) that you are trying to convert and assign to the aggregated (IOW, non-scalar) type ( struct key ). To fix this, change the new_node type to struct key * and rewrite the selection as follows:

 struct key *new_node = calloc(1, sizeof *new_node); 

Two things to note. First of all, drop the expression. malloc , calloc and realloc all return void * , which can be assigned to any type of object pointer without the need for casting 1 . In fact, the presence of a cast can potentially mask the error if you forget to include stdlib.h or otherwise do not have an declaration for malloc in area 2 .

Secondly, note that I am using the *new_node expression as an argument to sizeof , not a (struct key) . sizeof does not evaluate its operator (unless it is a variable array type, which is not the case); it just calculates the type of expression. Since the type of the expression *new_node is equal to the struct key , sizeof will return the correct number of bytes to store this object. This can save some maintenance headaches if your code is structured as

 T *foo; ... // more than a few lines of code foo = malloc(sizeof (T)) 

and you change the type foo in the declaration, but forget to update the call to malloc .

Also, it is not clear what you are trying to accomplish using the typedefs and struct definitions. The code

 typedef struct value_t value; struct value{ void* x; int y; value* next; value* prev; }; 

Don't do what you think. You create a name of typedef value , which is a synonym for type as-yet-undefined struct value_t . This value type is different from the struct value type that you create later (typedef names and struct tags live in different namespaces). Rewrite your structures to follow this model:

 struct value_t { void *x; int y; struct value_t *next; struct value_t *prev; }; typedef struct value_t value; 

In addition, life will be easier if you write your declarations so that * is associated with the declaration, and not a type 3 specifier. A declaration of type T* p parsed as if it were written by T (*p) . This will save you the embarrassment of writing int* a, b; and expects both a and b be pointers ( b is just a regular int ).


1 is one area where C and C ++ are different; C ++ does not allow implicit conversions between void * and other types of object pointers, so if you compile this as C ++ code, you will get an error message during compilation. In addition, prior to the adoption of the 1989 standard, *alloc functions returned char * , so in those days the cast was necessary if you assigned a different type of pointer. This should be a problem if you are working with a very old system.

2 - Before the standard 1999, if the compiler saw a function call without a previous declaration, it assumed that the function returned int (so you still sometimes see examples like

  main() { ... } 

in some textbooks; main implicitly printed to return int . Starting with C99, this is no longer permitted). Therefore, if you forget to include stdlib.h and call calloc (and you do not compile like C99), the compiler will assume that the function returns int and will generate machine code accordingly. If you leave the cast, the compiler issues a diagnostic that you are trying to assign an int value to the pointer, which is not valid. If you leave the actuation, the code will be compiled, but the value of the pointer can be changed at runtime (converting pointers to int and back to pointers will not make sense again).

3 - There are some rare instances limited by C ++, where the T* p style can make the code a little more understandable, but in general you better follow the T *p style. Yes, this is a personal opinion, but it is supported by non-trivial experience.

+2
source

calloc (3) returns a pointer to the allocated memory.

 struct key new_node = (struct key) calloc(1, sizeof(struct key)); 

it should be

 struct key* new_node = calloc(1, sizeof(struct key)); 
+1
source

You cannot assign a pointer to a variable other than a pointer. Change new_node as a pointer.

Also, to use the address of a variable, you need & , not * , so change it to struct value* y = &x;

Edit: your typedef is also wrong. cancel them.

+1
source

For the second problem, you want to use the ampersand "&" instead of the astriisk "*". The astriisk shares a pointer, the ampersand gives you a pointer to a value.

0
source

Source: https://habr.com/ru/post/1393066/


All Articles