In C you can either have a struct of another type "embedded" in your original struct, or you can use "pointers" - a pointer is a reference to another structure in memory -
And in practice, compared to relational databases, it works like an "id" from another table - only instead of an ID number (which we’re usually addicted to seeing sequentially, cute ID1 numbers, Id 2, id 3), we have a memory address. (which in modern architectures is a 64bit number "#muitolouco") .
Let me put the two examples:
struct categoria
{
int codigo_categoria;
char descricao_categoria[20];
};
struct produto
{
char nome[30];
struct categoria esta_categoria;
};
This way, you have a complete category, independent of any other instance of the same data, within your product. It’s simpler, because you don’t have to worry about pointer logic, etc -- if Oce creates a category, you can use a simple "=" sign to assign a copy of your category to the category within a product:
struct produto meu_produto;
struct categoria minha_categoria;
...
meu_produto.esta_categoria = minha_categoria;
printf("Descrição da categoria: %s\n", meu_produto.esta_categoria.descricao);
This will copy all the category struct fields to another struct within the product.
In real-world applications, it’s usually not what you want - as you put it, the interesting thing is to have a reference to another category - which can be in an array, or another data structure - in this case, the syntax is:
struct categoria
{
int codigo_categoria;
char descricao_categoria[20];
};
struct produto
{
char nome[30];
struct categoria *esta_categoria;
};
...
meu_produto.esta_categoria = &minha_categoria;
printf("Descrição da categoria: %s\n", meu_produto.esta_categoria->descricao);
In this case, what remains in the product struct is a reference for the content of the other struct (just like in the SQL relationship). If the original category struct is changed, the change can be seen by accessing the category through the product.
However there is a fundamental difference to an SQL relationship - references to pointer structures are valid only for the running process, loaded in memory. In a database reference, if you turn everything off, turn it on again, when loading the product, you will have a categorie_id that will still be valid in the table of categories.
In the C program, assuming that you create or use a Mechanism to persist the raw data of the structs between one execution and another of the program, when loading the data of a struct "product" the pointer it has to the category is invalid, and for all purposes, points to a random region of memory. So, for each struct that refers to others, in a system that needs to persist data - be it database, file, network, etc... (and also to release the memory of related structs, when the main struct is offset) - for this example, you could have a:
struct categoria
{
int codigo_categoria;
char descricao_categoria[20];
int referencias=0;
};
void produto_adiciona_categoria(struct produto *este_produto, struct categoria *esta_categoria) {
*produto->esta_categoria = esta_categoria;
esta_categoria->referencias += 1;
}
void produto_remove_categoria(struct produto *este_produto) {
struct categoria *tmp = este_produto->categoria;
este_produto->categoria=NULL;
if (--(tmp->referencias) <= 0) {
free(tmp)
}
}
Note that even in a small application, to avoid memory leakage problems, you would have to start counting how many references there are for each structure in memory - and create funnels to create and destroy each type of structure based on the reference count -- the management of this scale very fast - and when you realize you are creating an object orientation system to make your program (and therefore reinventing the wheel).
I end with two suggestions: stop any attempt to develop your code to understand "pointers" in C -they are logical, and it’s relatively easy to understand their mechanisms, if we’re focused on that - but if you’re going to let it in slowly, and "well, in the example there is this *, so I’ll put a * here and see if it works" - it gets complicated, tiring, and will generate aversive feelings.
The other recommendation is:
Unless you’re doing this to learn C as the ultimate goal, and not to have a functional program, I recommend using a higher-level language for this type of code.
In dynamic languages like Python, Javascript or Ruby, associating data as you want, which is done with "objects" in those languages, instead of C structs is tens of times simpler - even more so for those who are starting.
Yes, but the way to do this depends on the goal that needs to be achieved. Is there any code you’re using? This would help understand the intention.
– Maniero
The objective is to inform the category in the product through its code, to find out if there is a category already registered when the user informs the code of the category when.
– Jana Santos
Because basically what you’ve shown is already doing this. I don’t know if there is any real doubt. In this case the member
codigo_ligacao_categoria
will be completed with thecodigo_categoria
of the variable of a specific structure.– Maniero
It is that I wanted to ensure that the values of the code_category field do not change if there is already a category, it would be like a foreign key.
– Jana Santos
It’s hard to help from scratch.
– Maniero