Allocate memory in C for structure vector

Asked

Viewed 2,408 times

2

What is the right way to allocate memory to a vector of structures?

struct CARRO{
    int id;
    char fabricante[MAX];
    char modelo[MAX];
    int ano;
    char cor[MAX];
    int preco;
};

int main(){

    int qtd, i;
    scanf("%d", &qtd);

    struct CARRO *carros[qtd];

    *carros[qtd] = (struct CARRO *) malloc(qtd * sizeof(struct CARRO));

}
  • Buddy, you can take a look at this link which has a case similar to what you need (in the code on pages 4 and 5, it makes an allocation very similar to what you want). I hope it helps!

  • Did any of the answers solve your question? Do you think you can accept one of them? Check out the [tour] how to do this, if you haven’t already. You would help the community by identifying what was the best solution for you. You can accept only one of them. But you can vote on any question or answer you find useful on the entire site.

3 answers

3

It’s actually quite simple. I’m understanding that you want to make a dynamic allocation. So you don’t need anything from [qtd]. Either do it one way or do it another.

There are better ways to do this, but you learn one thing at a time.

#include <stdio.h>
#include <stdlib.h>
#define MAX 30

struct CARRO{
    int id;
    char fabricante[MAX];
    char modelo[MAX];
    int ano;
    char cor[MAX];
    int preco;
};

int main() {
    int qtd;
    scanf("%d", &qtd);
    struct CARRO *carros = malloc(qtd * sizeof(struct CARRO));
    free(carros); //só para usar a variável, neste caso não precisa
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

Note that I have not used cast because it can hide a programming error and assigns next to the statement which is the most intuitive and modern.

If it were static it would just be:

int qtd;
scanf("%d", &qtd);
struct CARRO carros[qtd];

Static allocation is always preferred when possible.

Actually in this specific case the term used is automatic allocation, because it is done in the stack or register (as a complex vector does not fit in the register, but a simple or scalar type could be). Static allocation can occur in the heap also, as long as it is part of a dynamically allocated structure. This is the case of char fabricante[MAX]; for example, which is allocated within CARRO so inline, but will only exist when dynamic allocation in the heap.

  • Only the return 0; in main ;-)

  • There’s no need to do this.

  • Brawl @bigown :D

2

You must set the pointer carros as just struct CARRO *carros. The way you wrote it, you were defining carros as a vector of pointers of structures, rather than simply a vector of structures.

Also, when assigning a value to the pointer, you should use only its name, without the asterisk. Otherwise, you will be referring not to the pointer, but to the memory space pointed by it (in case, the structure CARROS).

The code should then look like this:

int main() {

    int qtd;
    struct CARRO *carros;

    scanf("%d", &qtd);

    carros = (struct CARRO *) malloc(qtd * sizeof(struct CARRO));

}
  • 1

    Do the cast is harmful to the code and assign separate statement is a technique of the last century.

  • @bigown last century ok, but what good practice to talk about cast about malloc is harmful? As I recall, cast free of void* was C++, not something that should be used in C

  • @Jeffersonquesado in C++ is not to use malloc() if used he must have cast, in C should not have cast because it is another language with different semantics. https://answall.com/q/123208/101

  • @Bigown ok, I made a mess with C is C++ :P, switched was all. And yes, C++ long life to new

2

An alternative to dynamic memory allocation would be through the function calloc(), that in addition to allocating memory in the same way as the malloc(), is able to initialize the memory allocated with 'zeros':

void *calloc(size_t nmemb, size_t size);

It has a more 'intuitive' prototype because it takes two arguments: The amount of elements (nmemb) and the size of each of these elements (size).

Here’s an example of how to solve your problem:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define MAX         (100)
#define QTD_CARROS  (5)


struct CARRO {
    int id;
    char fabricante[MAX];
    char modelo[MAX];
    int ano;
    char cor[MAX];
    int preco;
};

typedef struct CARRO carro_t;


void carro_preencher( carro_t * c, int id, char * fab, char * mod, int ano, char * cor, int preco )
{
    c->id = id;
    strncpy( c->fabricante, fab, MAX );
    strncpy( c->modelo, mod, MAX );
    c->ano = ano;
    strncpy( c->cor, cor, MAX );
    c->preco = preco;
}


int main( int argc, char * argv[] )
{
    /* Cria array de carros */
    carro_t * carros = calloc( QTD_CARROS, sizeof(carro_t) );

    /* Preenche os dados de cada Carro na array */
    carro_preencher( &carros[0], 1000, "Volkswagen", "Kombi", 1980, "Branco", 1000 );
    carro_preencher( &carros[1], 2000, "Chevrolet", "Camaro", 2017, "Amarelo", 80000 );
    carro_preencher( &carros[2], 3000,"Fiat",  "Uno", 2005, "Cinza", 5000 );
    carro_preencher( &carros[3], 4000,"Ford", "Fiesta", 2001, "Vermelho", 10500 );
    carro_preencher( &carros[4], 5000,"Toyota", "Corolla", 2017, "Prata", 70000 );

    /* Libera array de carros */
    free(carros);

    return 0;
}

A second alternative would be to allocate through a pair of functions capable of building/destroying a single Carro.

These functions would be called for each element of the array, indenpendente, at the time of construction and destruction of each Carro.

Here is another more elaborate example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define QTD_CARROS  (5)


struct CARRO {
    int id;
    char * fabricante;
    char * modelo;
    int ano;
    char * cor;
    int preco;
};


typedef struct CARRO carro_t;


carro_t * carro_construir(  int id, char * fab, char * mod, int ano, char * cor, int preco )
{
    carro_t * c = calloc( 1, sizeof(carro_t) );

    c->id = id;
    c->fabricante = strdup(fab);
    c->modelo = strdup(mod);
    c->ano = ano;
    c->cor = strdup(cor);
    c->preco = preco;

    return c;
}


void carro_destruir( carro_t * c )
{
    free(c->fabricante);
    free(c->modelo);
    free(c->cor);
    free(c);
}


int main( int argc, char * argv[] )
{
    int i = 0;
    carro_t * carros[ QTD_CARROS ]; /* Array de carros */

    /* Constroi um Carro para cada elemento da array... */
    carros[0] = carro_construir( 1000, "Volkswagen", "Kombi", 1980, "Branco", 1000 );
    carros[1] = carro_construir( 2000, "Chevrolet", "Camaro", 2017, "Amarelo", 80000 );
    carros[2] = carro_construir( 3000, "Fiat",  "Uno", 2005, "Cinza", 5000 );
    carros[3] = carro_construir( 4000, "Ford", "Fiesta", 2001, "Vermelho", 10500 );
    carros[4] = carro_construir( 5000, "Toyota", "Corolla", 2017, "Prata", 70000 );

    /* Destroi cada Carro contido na array */
    for( i = 0; i < QTD_CARROS; i++ )
        carro_destruir( carros[i] );

    return 0;
}
  • Thank you Lacobus, your explanation and examples were very helpful. D

Browser other questions tagged

You are not signed in. Login or sign up in order to post.