"array type has incomplete element type" - c

I am new to C programming, and have the following code. I am facing following error.
typedef struct Vertex Vertex;
typedef struct Edge Edge;
struct Vertex {
bool known;
char id[25];
Edge edges[20];
int distance;
};
struct Edge {
Vertex target;
int weight;
};
typedef struct {
Vertex Nodes[20];
int pass;
int infinity;
} Graph;
The error it gives is:
array type has incomplete element type
Can someone please help me understand what is the problem?

typedef struct Vertex Vertex;
typedef struct Edge Vertex;
this is probably generating some name conflict just change the name of one of them.

The only way this will be possible, is using a mixture of pointers and addressing how you implement your Vertex and Edge structures:
/*your typedefs didn't make sense to me as it was conflicting. So, I edited it accordingly*/
//typedef struct Vertex Vertex;
//typedef struct Edge Vertex;
struct Vertex;
struct Edge;
typedef struct Vertex {
bool known;
char id[25];
struct Edge *edges;//This HAS to be a pointer.
int distance;
} Vertex;
typedef struct Edge {
Vertex target;
int weight;
} Edge;
typedef struct {
Vertex Nodes[20];
int pass;
int infinity;
} Graph;
Why does this work? Because of something called forward declaration:
...a forward declaration is a declaration of an identifier (denoting
an entity such as a type, a variable, or a function) for which the
programmer has not yet given a complete definition. It is required for
a compiler to know the type of an identifier (size for memory
allocation, type for type checking, such as signature of functions),
but not a particular value it holds (in case of variables) or
definition (in the case of functions)...

In this declaration
struct Vertex {
bool known;
char id[25];
Edge edges[20];
int distance;
};
the type Edge is not yet declared. The compiler here only knows that it will correspond to a struct Edge, but that struct itself is not known.

Can someone please help me understand what is the problem?
Arrays have the following properties:
All its elements have the same size.
The elements are stored contigously.
This allows to calculate the memory address of each element (e.g. id[i]) from the size and memory address of the first element and the index i.
To do this, the compiler needs to know how large the array elements are. When you declare the Vertex::edges[20] member, the compiler does not yet know, how large objects of type Edge are. Hence the compiler error.
One way to avoid this is, to define the Edge struct before the Vertex struct. In your case, this won't help, because the Edge::target is of type Vertex and you will get a similar error. Memory addresses of struct members are calculated using the memory address of the object and adding the sizes of the members (and possibly some padding) that precede the requested member.
In such a case with circular dependencies, pointers as members can be used, because a pointer to a struct has the same size, no matter which members the struct has, that the pointer points to.

Think about it: the compiler has to know the size of the Vertex and Edge structures. If you make Edge contain a Vertex and Vertex contain an Edge, it can't really sort out the size. The solution is to provide just a pointer to the structure (pointer size should be known to the compiler). I would use a jrd1 version with a small change:
struct Edge {
struct Vertex* target;
int weight;
} Edge;
typedef struct Vertex {
bool known;
char id[25];
struct Edge edges[20];
int distance;
} Vertex;
typedef struct {
Vertex Nodes[20];
int pass;
int infinity;
} Graph;
That should work just fine.
Furthermore, if each edge is supposed to point the Vertex where it is contained, you don't really need to store that pointer, you could use something like the container_of macro in the linux kernel if you want.

Related

C circular dependency for embedded types (not pointer)

I came across this solution for the problem and it solved by forward referencing the struct.
But I've a different scenario, in my case the struct is embedded. My actual problem has a long dependency chain, a -> b -> c -> d -> a (-> means includes or depends upon) so I'm going to use the given solution from the post.
Q. Is it possible to have embedded type struct edgelist edges?
Error: 1field has incomplete type 'struct edgeList'
struct edgelist;
typedef struct
{
char* name;
float x, y;
struct edgelist* edges;
} vertex;
This is an incomplete type:
struct edgelist;
This code is correct because it's allowed to have a pointer to an incomplete type:
typedef struct
{
char* name;
float x, y;
struct edgelist* edges; // you can have pointers to incomplete types
} vertex;
But as soon as you use this, your code becomes incorrect because edges is not a pointer:
struct edgelist edges;
In order to be able to use a variable of type struct edgelist, the struct needs to be defined somewhere.
So this would be correct:
struct edgelist // declares an actual (complete) type struct edgelist
{
// whatever declaration you want
};
struct edgelist edges;

C multiple struct with only one node

After juggling and trying to learn how to get this done I thought it's time to ask the experts.
I have more than one structures and would like to "manipulate" the data in them using only one node.
What is the best way to do this?
code example:
typedef struct printQuality{ int dpi; } quality ;
typedef struct paperSize{ char* dim; } sizes ; //this would be A3 , A4 this is why i picked char
typedef struct printColour{ char* color; } colors;
typedef struct printStyle{ char* side; } sides;
typedef struct printOrientation { char* orientation; } orientations;
typedef union printOptions{
quality dpi;
sizes size;
colors color;
sides side;
orientations orientation;
} options;
struct optNode{
options* inf;
optNode* next;
optNode* prev;
};
From your comments, I believe your issue has to do with the behavior of Unions in C vs structs. In C/C++, Unions are structures which can only instantiate one of their values at a given time. With your printOptions union, you have 5 variables. At any given time, only one of those variables (the last one you set) is guaranteed to hold a value. Here is a good article on how Unions work: https://www.programiz.com/c-programming/c-unions. Structs in C/C++ do not have this behavior. Whichever values you set remain set until the instance of the struct goes out of scope or is deleted. I think that if you make printOptions a struct, you will be able to access all of your other structs from your options pointer in your optNodes.

Structures in C:Why this does not show incompatible type for fied fe;

Could someone please explain first 2 cases given below for structures in c?and how it works?
Case:1
struct vertex{
int info;
struct vertex * nextertex;
struct edge *firstEdge;}; //why no error as incompatible type for field firstEdge?
This code does not generate error!We do not have struct edge in the whole code!!
Case:2
struct vertex{
int info;
struct vertex * nextertex;
struct edge *firstEdge;};
struct edge{
struct vertex * destVertex;
struct edge *nextEdge;};
Same as case:1,difference being we have struct edge after struct vertex definition. No errors!
Case:3
struct vertex{
int info;
struct vertex * nextVertex;
struct edge firstEdge;};
struct edge{
struct vertex * destVertex;
struct edge *nextEdge;};
This seems more obvious.Throws error as incompatible type for field firstEdge in struct v.
C has a concept of complete and incomplete types.
C says an incomplete type lacks sufficient information to determine the size of objects of that type, while a complete type provides
sufficient information.
C does not allow you to declare a structure type with a member of an incomplete type but you are allowed to declare a structure type with a member of a type pointer to an incomplete type. In the latter case trying to a dereference the pointer to the incomplete type is not valid if the type has not been completed (by declaring the structure type with its defining content later in the same scope).
Replacing struct edge firstEdge with struct edge *firstEdge eliminates the error or define edge then vertex.
In the first two cases, you're defining a pointer to some structure[struct edge *], so the definition is valid. The definition of struct edge need not precede the struct vertex definition.
In the third case, you're defining a variable of a structure. To do that, the compiler needs to have the definition of that other structure before it is used.

Pointer typecasting in c

I am writing an implementation of graphs in C language. I came across a situation where I am not able to figure out the reason for the way the compiler is behaving with a pointer typecast warning.
Here are the structures;
#define MAXV 10
typedef struct {
int y;
int weight;
struct edgenode *next;
} edgenode;
typedef struct {
edgenode *edge[MAXV+1];
int degree[MAXV+1];
// other info of graph
} graph;
// operation in some other function
p->next = g->edge[x];
I got a pointer typecast warning[enabled by default] when I do this kind of operation.
I was not able to remove this warning even after trying to typecast with every possible cast.
Finally I made a code change in the structure and suddenly the warning was gone.
The structure code change was this:-
typedef struct edgenode { // note that I have added structure name here
// same as above definition
} edgenode;
// operation in some other function
p->next = g->edge[x];
Now the warning is gone and code runs without any warnings.
I do not understand why is this happening; can anybody help me with this problem?
The problem is here:
typedef struct {
int y;
int weight;
struct edgenode *next;
} edgenode;
It is not clear what type struct edgenode *next; is referring to (it doesn't matter; somewhere, presumably, there's a struct edgenode defined), but it is not this structure because it has no tag. You need:
typedef struct edgenode
{
int y;
int weight;
struct edgenode *next;
} edgenode;
Now the pointer refers to another structure of this same type. So, the fix you found was the correct fix for your problem.
Remember: a typedef is an alias (alternative name) for an existing type. You created a type name edgenode, but you had not defined the type struct edgenode. You don't have to fully define a structure type before you create pointers to it; this can be a good way of creating 'opaque types'.
The other way to define things is:
typedef struct edgenode edgenode;
struct edgenode
{
int y;
int weight;
edgenode *next;
};
This says that the type name edgenode is an alias for a struct edgenode; the structure definition then tells the compiler what a struct edgenode looks like.

C: structs in structs

My assignment is to create a simple graph that has both Nodes and Edges.
In my header file which was given and cant't be modified I have
typedef struct Edge_s* Edge;
typedef struct Node_s* Node;
typedef struct Graph_s* Graph;
and in my graph.c
typedef struct{
size_t w;
struct Node_s* target;
}*Edge;
typedef struct{
size_t value;
Edge* edges;
size_t s;
}*Node;
typedef struct{
Node* nodes;
size_t n;
Edge* edges;
size_t e;
}*Graph;
Edge create_edge(Node t, size_t w){
Edge ret = malloc(sizeof(*ret));
ret->target = t;
ret->w = w;
return ret;
}
This gives a warning on compile
warning: assignment from incompatible pointer type
I'm kind of confused here, what am I getting wrong and how should I fix it? The program is almost working and I'm getting one strange bug that I believe might be because of this.
Your typedef-definitions are mixed up badly. I'm surprised it even compiles.
You first defined typedef-name Edge as
typedef struct Edge_s* Edge;
and then later re-defined it as
typedef struct{
size_t w;
struct Node_s* target;
}*Edge;
These two definitions define Edge in two completely unrelated ways. (All C compilers I know would immediately report an error if the first group of declarations would meet the the second group in the same translation unit.)
I'd say that your second struct definition should be simply
struct Edge_s {
size_t w;
struct Node_s* target;
};
Don't attempt to redefine an existing typedef-name. It is simply illegal in C.
Ask yourself what type of object does ret->target point to and what type of object is it? Are they the same types of objects?

Resources