How to make cross pointers in structs - c

So here's my problem, I want to create a graph-database. My concept idea is a node (which will be of type "Vrtc" in the code. It will cointain an (int) id, a (char*) string (called "str") and a list (l_est) of paths in and out.
The list will contain an "array" of pointers to nodes, the amount of nodes in the list, and the maximum number of nodes.
typedef struct Vrtc
{
int id;
char *str;
l_est *pathsIn;
l_est *pathsOut;
} Vrtc;
typedef struct l_est{
Vrtc **Vert;
int qtdElem;
int maxElem;
} l_est;
As you may know, there'll be a problem of "Unknow type/Type undeclared inside the node. I was hoping anyone could give a tip of how to do it, if it is possible.

You have to use a forward declaration:
typedef struct l_est l_est;
typedef struct {
int id;
char *str;
l_est *pathsIn, *pathsOut;
} Vrtc;
typedef struct l_est {
Vrtc **Vert;
int qtdElem, maxElem;
} l_est;
The first type definition of struct l_est is a so-called "incomplete type". This type may not be used for variables or with sizeof but it may be used to declare pointer.
The incomplete type may later be overridden by a "complete type" without complaints of the compiler.
Similar solutions can be found in other languages (e.g. Pascal).

Related

Declare an array of structures

I am trying to create an array of structures but it appears this bug:
"Error, array type as incomplete element type"
typedef struct {
char data[MAX_WORD_SIZE];
int total_count;
Occurrence_t reference[MAX_FILES];
int nfiles;
} Word_t;
struct Word_t array[a];
TL;DR
Either change you struct definition
struct Word_t {
char data[MAX_WORD_SIZE];
int total_count;
Occurrence_t reference[MAX_FILES];
int nfiles;
};
Or (and not both), the array declaration:
Word_t array[a];
What you did is define an un-named structure, to which you gave an alternative name with a typedef. There is no struct Word_t, only a Word_t type defined.
The tag namespace (where the names that you use after struct/union/enum reside) is separate from the global namespace (where file scope typedefed names reside).
Many programmers feel that lugging around a struct tag type name is cumbersome, and you should always do a typedef for the struct name. Others feel this is an abuse of typedef-ing, and that the keyword conveys a lot of meaning; to them the typedef is syntactic sugar without any real abstraction.
Whichever way you choose to write you code, stick to it, and don't confuse the two namespaces.
You are using typedef in the first place hence you are not supposed to write the struct anymore . look here
typedef struct {
char data[MAX_WORD_SIZE];
int total_count;
Occurrence_t reference[MAX_FILES];
int nfiles;
} Word_t;
Word_t array[a];
It will work

Handling incomplete type errors in C

I have a struct called 'residence' below. It contains a person_list struct where the person_list struct contains a struct for each person.
typedef struct a_person
{
char name [MAX_LENGTH];
int age;
} person;
typedef struct person_list
{
struct person people[MAX_ALLOWED];
} personList;
struct residence {
char residence_name [MAX_LENGTH];
struct personList resident_list;
};
I'm getting these errors upon compilation:
error: resident_list; has incomplete type
error: array type has incomplete element type (#struct person
people[MAX_ALLOWED];)
If you need additional code or information please don't hesitate to ask
You could predeclare every struct that you are further defining, e.g. by starting your file (or your header file) with
struct a_person; // should be person_st
struct person_list; // should be person_list_st
then you may have a pointer to such struct (even without having defined the fields of that struct yet).
However, when you define a struct by listing all its fields, every field should have a size known to the compiler.
Some further hints (including conventions):
you could (and I do, conventionally) name every struct tag ending with e.g. _st (this is a convention that I do like to follow)
you can make a typedef together with the struct declaration, e.g.
typedef struct a_person_st Person;
BTW, I am following the convention (inspired by GTK) that a structure type starts with a capital letter.
I don't recommend having typedef for pointers. Being a pointer type is really important in C, and I feel it should be kept apparent. So I recommend against typedef Person*PersonPtr; (but again, this is my convention).
You would later define the struct by listing its fields, e.g.
struct person_st { // or Person
char name[MAX_LENGTH];
int age;
}; // end of definition of struct person_st
You might be interested (assuming a C99 or C11 compiler) by flexible array members (it is a C feature, not a C++ one, and that flexible array member should always be the last of its containing struct).

Why does "struct T* next" compile when T isn't an existing type?

I am using MinGW on Windows. I am building linked list and I am confused with this.
#include <stdio.h>
#include <stdlib.h>
typedef struct Data
{
int x;
int y;
struct BlaBla * next; /*compiles with no problem*/
}List;
int main(void)
{
List item;
List * head;
head = NULL;
return 0;
}
I now that struct can't have struct variable(object, instance of that struct), but can have pointer of that struct type. Didn't know that pointer can be pointer of unexisting type. struct BlaBla * next;(not for linked list, it must be struct Data * next but mean general talking)
Yes, you can, because then the compiler, upon encountering the unknown type name for the first time, assumes that there's somehwere a struct type definition with this name. Then it will forward-declare the struct name for you, let you use it as a pointer, but you can't dereference it nor can you do pointer arithmetic on it (since it's an incomplete type).
The compiler will accept code such as your example:
typedef struct Data
{
int x;
int y;
struct BlaBla * next; /*compiles with no problem*/
}List;
This is okay because the size of pointers is known to the compiler, and the compiler is assuming that the struct will be defined before it is dereferenced.
Because the compiler acts this way, it's possible to do this:
typedef struct Data
{
int x;
int y;
struct Data * next; /* points to itself */
} List;
However, if you were to include the struct inline, like this:
typedef struct Data
{
int x;
int y;
struct BlaBla blaStruct; /* Not a pointer. Won't compile. */
}List;
The compiler can't work out how big struct Data is because it doesn't know how big struct BlaBla is. To get this to compile, you need to include the definition of struct BlaBla.
Note that, as soon as you need to access the members of struct BlaBla, you will need to include the header file that defines it.
It depends on what you mean by "unexisting". If you haven't even declared BlaBla, you'll get an error.
If you've declared it but not yet defined it, that will work fine. You're allowed to have pointers to incomplete types.
In fact, that's the normal way of doing opaque pointers in C.
So, you might think that this is invalid because there's no declaration of struct BlaBla in scope:
typedef struct Data {
struct BlaBla *next; // What the ??
} List;
However, it's actually okay since it's both declaring struct BlaBla and defining next at the same time.
Of course, since definition implies declaration, this is also okay:
struct BlaBla { int xyzzy; };
typedef struct Data {
struct BlaBla *next; // What the ??
} List;
In order to declare a variable or field of a given type, pass one as a parameter, or copy one to another of the same type, the compiler has to know how many bytes the variable or field occupies, what alignment requirements it has (if any), and what other pointer types it's compatible with, but that's all the compiler needs to know about it. In all common dialects of C, a pointer to any structure will always be the same size and require the same alignment, regardless of the size of the structure to which it points or what that structure may contain, and pointers to any structure type are only compatible with other pointers to the same structure type.
Consequently, code which doesn't need to do anything with pointers to a structure except allocate space to hold the pointers themselves [as opposed to the structures at which they point], pass them as parameters, or copy them to other pointers, doesn't need to know anything about the structure type to which they point beyond its unique name. Code which needs to allocate space for a structure (as opposed to a pointer to one) or access any of its members must know more about its type, but code which doesn't do those things doesn't need such information.

pointer to struct in struct in c

I have trouble with structures in c.
I have two structures like
typedef struct
{
char isim[256];
int deger;
struct ekstra *sonra;
}ekstra;
typedef struct
{
char *name;
int val;
struct ekstra *next;
}node;
/*and main is*/
int main()
{
int i;
node dizi[12];
for(i=0;i<12;i++)
{
dizi[i].name = malloc("asdasd"*sizeof(int));
strcpy (dizi[i].name,"asdasd");
/*and trouble starts here*/
**dizi[i].next = malloc(sizeof(ekstra));
printf("%s",dizi[i].next->isim);**
}
}
the error is
error: dereferencing pointer to incomplete type
How can I hold place for dizi[i].next?
struct ekstra is not the same as ekstra.
Your first struct typedef should be declared as follows:
typedef struct ekstra
{
char isim[256];
int deger;
struct ekstra *sonra;
}ekstra;
typedef struct... ekstra;
This means: "create a type that is called ekstra". From now on this type can be used just as any variable type (int, char etc).
struct ekstra *next;
This means: Somewhere in my program there is a struct of some type, I don't know what it contains, but I want to point to an element of that type. This is the meaning of incomplete type.
To fix your problems, simply replace this row with ekstra *next;.
More comments not directly related to the question:
dizi[i].name = malloc("asdasd"*sizeof(int));
This is pure nonsense code. It means: "Create a constant string literal in the ROM part of my program. In this constant string literal, store the letters "asdasd" and a null termination character. Then take the address of this ROM memory location, which is completely irrelevant to my application, convert it to an integer so that I get a 32-bit nonsense number. Then multiply this nonsense number with the sizeof an int, which doesn't make any sense to anyone either. Then take this completely nonsense result and allocate a random amount of dynamic memory based on this. Then watch the program crash.
I don't understand code line like
malloc("asdasd"*sizeof(int));
But, I think you problem should slove like this
dizi[i].next = (ekstra *)malloc(sizeof(ekstra));
and you struct define should like
typedef struct node{
int a;
int b;
struct node *next;
}node;

array type has incomplete element and field 'status' has incomplete type

Im a NOOB with programming and Im really stumped. I get "array type has incomplete element and field 'status' has incomplete type" errors when i compile this code. I have this linked with another pile of code "which is thankfully error free". the errors are identified in this section so any help will be appreciated.
Thank you. here's the C code
struct name;
struct book;
struct Library{
struct Book collection[100];
struct person patrons[100];
int totalBooks;
int totalPatrons;
};
struct person{
char first[32];
char last[32];
enum Stat status;
};
struct Book{
char title[32];
char author[32];
int id;
int year;
int status;
};
enum Stat{ACTIVE=1, INACTIVE=2, CHECKED_OUT=3, CHECKED_IN=4, UNDER_REPAIR=5, LOST=6};
~
Looks like you've come from a C background - unfortunately it isn't valid C# code.
Arrays are defined as char[] first; (also size isn't relevant at this point)
Enums do not need an enum prefix when defining the variables. Same with structs.
You don't need to declare structs for name and book
In fact, I think you're probably wanting to use a string variable instead of char arrays.
struct Library{
Book[] collection;
Person[] patrons;
};
struct Person{
string first;
string last;
Stat status;
};
struct Book{
string title;
string author;
int id;
int year;
int status;
};
enum Stat{ACTIVE=1, INACTIVE=2, CHECKED_OUT=3, CHECKED_IN=4, UNDER_REPAIR=5, LOST=6};
There are basically two things wrong with the section of code you showed that the compiler is complaining about:
C is case sensitive: struct book and struct Book are two different types.
In C, you cannot refer to a type until it has been declared; that is, you cannot define a field of type enum Stat before you define enum Stat.
The actual problem, then, is that the compiler doesn't know what a struct Book is at the point where you try to define an array of them. Similarly, it doesn't know what an enum Struct is at the point where you define a field of that type.
(Mostly unimportant tangent: The reason you are getting the "incomplete type" errors instead of something slightly more useful is because the compiler allows you, in certain cases, to use struct types that you don't actually have the full definition of, but only if you use them through so-called "opaque" pointers (that is, you never actually use the type, you just pass pointers to them around.) In your case you are telling the compiler you want an array of struct Book, which requires a completely define type, which you don't have.)
To fix it you just need to reorder your type definitions so that none of them are used before they're defined, and use consistent casing throughout. Also, while it's legal to continue to refer to struct foo and enum bar in the rest of your program, most people would create a typedef (basically, type aliases) instead. For example:
typedef enum tagStat {
ACTIVE=1,
INACTIVE=2,
CHECKED_OUT=3,
CHECKED_IN=4,
UNDER_REPAIR=5,
LOST=6
} Stat;
typedef struct tagPerson {
char first[32];
char last[32];
Stat status;
} Person;
typedef struct tagBook {
char title[32];
char author[32];
int id;
int year;
int status;
} Book;
typedef struct tagLibrary {
Book collection[100];
Person patrons[100];
int totalBooks;
int totalPatrons;
} Library;
It looks like you are trying to use the Stat enum in your definition of person before you declare/define it. Add enum Stat; where you have the struct statements at the top of the file.

Resources