简体   繁体   中英

C Malloc of array within a struct

I'm trying to malloc a struct with a value from main. I've searched for ways of doing it but couldn't find an answer. I have 3 types of coins whose prices I want to put into ret . How do I declare ret from the struct?

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

typedef struct
{

    double *ret;

}coin;


void ini(int a)
{
    ret = (double*)malloc(a*sizeof(double));
}


int main(void){

    long int a=250;
    int n_coins=3;


        coin *m = (coin*)malloc(n_coins*sizeof(coin));

        ini(a);

        m[0].ret[0] = 2000;
        printf("%lf", m[0].ret[0]);



    return 0;
}

First of all return is a reserved keyword in C and you can not use a reserved keyword as a variable name.

Second,If you want to allocate memory for array of any data type in other function then,declare a variable in the function,call malloc ,allocate required space through malloc and return the address of the first element of allocated space.If you do not return the address the allocated space would not be known to the called function(here main() ) and it could not be able to access the allocated memory space.You can do like this:

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

typedef struct
{
   double *var;
}moeda;


double *ini(int n)
{
   double *arr;
   arr = malloc(n*sizeof(*arr));
   return arr;
}

int main(void){

   long int a=250;

    moeda m;

    m.var=ini(a);

    m.var[0] = 2000;
    printf("%lf", m.var[0]);



    return 0;
}

If I had your code and had to improve it, I'd go for

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

// The kernel style guide https://www.kernel.org/doc/html/v4.10/process/coding-style.html discourages typedefs for structs
typedef struct moeda {
    double *return_value;
} moeda;


// return a struct here:
moeda initialize_return(int a)
{
    moeda ret;
    ret.return_value = malloc(a*sizeof(double));
    return ret;
}


int main(void) {
    long int a=250;

    moeda m = initialize_return(a);

    m.return_value[0] = 2000;
    printf("%lf", m.return_value[0]);

    return 0;
}

(it is better to have all identifiers in English).

This would be the first step to do. Then I might realize that the struct isn't really needed and replace it:

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

double * initialize_double_array(int a)
{
    return malloc(a*sizeof(double));
}

int main(void) {
    long int a=250;

    double * arr = initialize_double_array(a);

    arr[0] = 2000;
    printf("%lf", arr[0]);

    return 0;
}

OTOH, if there are other fields in the said struct, I might decide if they are supposed to be initialized along with this array or not.

Some variants:

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

// The kernel style guide https://www.kernel.org/doc/html/v4.10/process/coding-style.html discourages typedefs for structs
struct moeda {
    int num_values;
    double *values;
};

// only fill a struct here:
// i. e. take a pre-initialized struct and work with it:
void moeda_alloc_values(struct moeda * data) 
{
    data->return_value = malloc(data->num_values * sizeof(double));
}

// return a struct here:
struct moeda initialize_moeda(int num) 
{
    struct moeda ret;
    ret.num_values = num;
    ret.return_value = malloc(num * sizeof(double));
    // or just moeda_alloc_values(&ret);
    return ret;
}

int main(void) {
    long int a=250;

    struct moeda m = initialize_return(a);
    m.return_value[0] = 2000;
    printf("%lf", m.return_value[0]);

    struct moeda m2;
    m2.num_values = 20;
    moeda_alloc_values(&m2);
    m2.return_value[0] = 2000;
    printf("%lf", m2.return_value[0]);

    return 0;
}

The struct returning function has the advantage that you have a "readily filled" structure after return.

The other function which modifies a struct via a pointer on it has the advantage that it can work on any, possibly pre-filled, possibly malloced struct and that it can work on single fields instead having to consider all fields.

The return is keyword in c. You can't use this as variable name. Also the question is not clear to me. what is "moeda m;" moeda here? I am sorry if this is not English C.

I'm assuming you just mean you're trying to allocate memory to a struct from a function called in main. I've changed your variable names just for clarity. So, first as others have said, you can't use return as a variable name. I'd also recommend using the size of the struct rather than just the double because in future you'll likely have more than one variable in the struct.

if you want to use a function from main, you'll have to pass a pointer to the function and then use malloc to assign memory to it and then return it. Or you could make the struct pointer global as another option.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "stdafx.h"
#include <malloc.h>

typedef struct
{
    double number;
}example;

example *allocateMemory(int a, example *s)
{
    s = (example*)malloc(a * sizeof(example));
    return s;
}

int main() {

    long int a = 250;
    example *structure = NULL;
    structure = allocateMemory(a, structure);

    structure[0].number = 2000;

    printf("%lf\n", structure[0].number);

    //cleaning up memory
    free(structure);
    structure = NULL;
    return 0;
}

Just some other notes, I let my example structure equal null as the compiler was complaining about an uninitialized local variable.

In your code, you had this.

m.retorno[0] = 2000;

but i assumed you wanted to access the first number in your struct array, so that should be:

structure[0].number = 2000;

For this specific example I would do something like the following:

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

typedef struct
{
   size_t  nLen;    // number of elements allocated for var
   double *var;     // pointer to a list of double variables
} moeda;

// struct is small so just initialize the whole thing and return it
// from the initialization routine.
moeda iniMoeda (size_t n)
{
   moeda x = {0};

   x.var = malloc(n * sizeof(double));   // try to allocate the requested number of doubles
   if (x.var) x.nLen = n;     // if allocated then remember number of doubles

   return x;
}

// free a moeda variable. we require a pointer so that we can reset
// the moeda variable to a known state of NULL pointer and zero allocation
// length so that we can easily catch using the variable after the memory
// has been freed. Hope for Address exception on a NULL pointer if this
// variable is used after freeing.
void freeMoeda (moeda *x)
{
    // free the allocated doubles and clear everything.
    // if x->var is NULL then free() does nothing.
    free (x->var); x->var = NULL; x->nLen = 0;
}

int main(void)
{
    size_t  a = 250;
    moeda   m = iniMoeda (a);

    if (m.var) {
        // allocation worked so lets test our space
        m.var[0] = 2000;
        printf("%lf", m.var[0]);
    } else {
        printf ("m.var is NULL.\n");
    }

    freeMoeda (&m);
    return 0;
}

the following proposed code:

  1. cleanly compiles
  2. documents why each header file is included
  3. performs the desired operation
  4. cleans up after it self
  5. contains embedded comments about each step in the code

Note: code must be consistent, readable, and perform the desired functionality

And now, the proposed code:

// for ease of readability and understanding:
// 1) insert a space:
//    after commas,
//    after semicolons,
//    inside brackets,
//    inside parens,
//    around C operators
// 2) separate code blocks
//    ( 'for' 'if' 'else' 'while' 'do...while' 'switch' 'case' 'default' )
//    via a single blank line
// 3) variable (and parameter) names should indicate
//    'content' or 'usage' (or better, both)

#include <stdio.h>   // printf(), perror()
#include <stdlib.h>  // malloc(), free(), exit(), EXIT_FAILURE
// do not include header files those contents are not used
//#include <math.h>
//#include <string.h>

// added 'sCOIN' tag name to make it easier to use debugger
// since most debuggers use the tag name to reference fields inside a struct
typedef struct  sCOIN
{
    double *ret;
} coin;


int main( void )
{
    // 'malloc()' expects its parameters to be of type 'size_t'
    size_t n_coins=3;
    coin  mycoin;

    // do not cast the returned value from 'malloc()', 'calloc()', 'realloc()'
    // as the returned type is 'void*' which can be assigned to any pointer
    //coin *m = (coin*)malloc(n_coins*sizeof(coin));
    mycoin.ret = malloc( n_coins * sizeof( double ) );
    // always check to assure the operation was successful
    if( !mycoin.ret )
    {
        // 'perror()' outputs the enclosed text
        // and the text of why the system thinks the error occurred
        // to 'stderr'
        perror( "malloc failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, malloc successful

    // the field in 'coin' is declared a DOUBLE so assign a double
    // not a integer.  I.E include a decimal point '.'
    mycoin.ret[ 0 ] = 2000.0;
    printf( "%lf", mycoin.ret[ 0 ] );

    // code should always clean up after itself
    // I.E. don't leave a mess nor depend on the OS to cleanup.
    free( mycoin.ret );
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM