Allocate memory in C for structure vector

1

What is the right way to allocate memory for an array vector?

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));

}
    
asked by anonymous 27.06.2017 / 04:25

3 answers

3

It's actually quite simple. I understand that you want to make a dynamic allocation. So you do not need anything like [qtd] . Either do it one way or do another.

You have better ways to do this, but you will 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 precisaa
}

See running on ideone . And no Coding Ground . Also put it in GitHub for future reference .

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

If it were static then it would be just:

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

Static allocation is always preferred when possible.

In fact, in this specific case, the term used is automatic allocation, because it is done in the stack or register (because a complex vector does not fit in the register, but a simple or a scalar type could be ). Static allocation can occur in the heap as well, 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 inline , but will only exist when dynamic allocation in heap .

    
27.06.2017 / 06:37
2

You should set the carros pointer to be only struct CARRO *carros . As you wrote it, you were setting carros to be a vector of pointers of structures, rather than just a vector of structures.

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

The code should look like this:

int main() {

    int qtd;
    struct CARRO *carros;

    scanf("%d", &qtd);

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

}
    
27.06.2017 / 06:43
2

An alternative to dynamic memory allocation would be through the calloc() function, which in addition to allocating memory in the same way as 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 receives two arguments: The amount of elements ( nmemb ) and the size of each of these elements ( size ).

Here is 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, independently, at the time of the 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;
}
    
27.06.2017 / 15:36