How to write own function to allocation a set of structures?

Discussion in 'C Programming' started by Martin De Kauwe, Mar 20, 2012.

  1. Hi,

    I currently allocate a series of structures...

    in the .h file

    typedef struct {
    FILE *in_fp;
    etc....
    } control_struct;

    then in the main func:

    control_struct *ctrl;
    if ((ctrl = malloc(sizeof(control_struct))) == NULL) {
    fprintf(stderr, "control structure: Not allocated enough memory
    \n");
    exit(EXIT_FAILURE);
    }

    I would like to write my own generic function to take the malloc
    section to tidy up the code (as I have a number of structures to
    allocate), i.e. so instead in the main I would have something like

    allocate_structure(&ctrl);

    and

    void allocate_structure(structure *s) {
    if ((s = malloc(sizeof(structure))) == NULL) {
    fprintf(stderr, "Structure: Not allocated enough memory\n");
    exit(EXIT_FAILURE);
    }
    }

    But I am not sure how to pass the structure when it is unallocated,
    i.e. how to set up the function declarations.

    Any assistance would be very helpful

    thanks.
     
    Martin De Kauwe, Mar 20, 2012
    #1
    1. Advertising

  2. Martin De Kauwe

    Ian Collins Guest

    On 03/20/12 03:32 PM, Martin De Kauwe wrote:
    > Hi,
    >
    > I currently allocate a series of structures...
    >
    > in the .h file
    >
    > typedef struct {
    > FILE *in_fp;
    > etc....
    > } control_struct;
    >
    > then in the main func:
    >
    > control_struct *ctrl;
    > if ((ctrl = malloc(sizeof(control_struct))) == NULL) {
    > fprintf(stderr, "control structure: Not allocated enough memory
    > \n");
    > exit(EXIT_FAILURE);
    > }
    >
    > I would like to write my own generic function to take the malloc
    > section to tidy up the code (as I have a number of structures to
    > allocate), i.e. so instead in the main I would have something like
    >
    > allocate_structure(&ctrl);
    >
    > and
    >
    > void allocate_structure(structure *s) {
    > if ((s = malloc(sizeof(structure))) == NULL) {
    > fprintf(stderr, "Structure: Not allocated enough memory\n");
    > exit(EXIT_FAILURE);
    > }
    > }
    >
    > But I am not sure how to pass the structure when it is unallocated,
    > i.e. how to set up the function declarations.


    Either return the value allocated, or pass a pointer to the pointer:

    structure* allocate_structure()
    {
    structure* s = malloc(sizeof *s);
    //error check
    return s;
    }

    Or

    void allocate_structure( structure** s )
    {
    *s = malloc(sizeof *s);
    //error check
    }

    --
    Ian Collins
     
    Ian Collins, Mar 20, 2012
    #2
    1. Advertising

  3. Is your function going to allocate space for exactly one object of the
    same structure type each time? If so, Ian's suggestions should work
    just fine.

    If it is a variable quantity but always the same structure type, then
    pass the quantity as a parameter, use it in the call to malloc, and
    still follow Ian's suggestions.

    If the structure type also varies, then something like

    void * alloc_struct(size_t struct_size, int quantity)
    {
    void *ptr = malloc(struct_size * quantity);
    if (!ptr)
    {
    /* your error logic here */
    }
    return ptr;
    }

    could be called with code like

    struct1_ptr = alloc_struct(sizeof(struct1), 5);
    struct2_ptr = alloc_struct(sizeof(struct2), 8);

    On Mon, 19 Mar 2012 19:32:28 -0700 (PDT), Martin De Kauwe
    <> wrote:

    >Hi,
    >
    >I currently allocate a series of structures...
    >
    >in the .h file
    >
    >typedef struct {
    > FILE *in_fp;
    > etc....
    >} control_struct;
    >
    >then in the main func:
    >
    >control_struct *ctrl;
    >if ((ctrl = malloc(sizeof(control_struct))) == NULL) {
    > fprintf(stderr, "control structure: Not allocated enough memory
    >\n");
    > exit(EXIT_FAILURE);
    >}
    >
    >I would like to write my own generic function to take the malloc
    >section to tidy up the code (as I have a number of structures to
    >allocate), i.e. so instead in the main I would have something like
    >
    >allocate_structure(&ctrl);
    >
    >and
    >
    >void allocate_structure(structure *s) {
    > if ((s = malloc(sizeof(structure))) == NULL) {
    > fprintf(stderr, "Structure: Not allocated enough memory\n");
    > exit(EXIT_FAILURE);
    > }
    >}
    >
    >But I am not sure how to pass the structure when it is unallocated,
    >i.e. how to set up the function declarations.
    >
    >Any assistance would be very helpful
    >
    >thanks.


    --
    Remove del for email
     
    Barry Schwarz, Mar 20, 2012
    #3
  4. Sorry I am not sure I quite sure I followed that. I do have variable
    length structures, e.g. some are X parameters long, some are a set of
    controlling flags. I tried implementing the first example, but I am
    clearly misunderstanding how to do this.

    in the .h file

    typedef struct {
    FILE *ifp;
    int num_days;
    etc...
    } control_struct;

    void allocate_structure(structure **);

    in the .c file

    int main(int argc, char **argv)
    {
    /* Allocate all structures */
    control_struct *ctrl;
    allocate_structure(&ctrl);
    etc...

    void allocate_structure(structure **s)
    {
    if ((*s = malloc(sizeof(*s))) == NULL) {
    fprintf(stderr, "some msg\n");
    exit(EXIT_FAILURE);
    }

    }

    it says it doesn't know what 'structure' is when it compiles. I must
    be misunderstanding as this is what I didn't get, i.e. how to pass the
    structure, what you call it when you pass it to the function.
     
    Martin De Kauwe, Mar 20, 2012
    #4
  5. Martin De Kauwe

    Ian Collins Guest

    On 03/20/12 07:58 PM, Martin De Kauwe wrote:
    > Sorry I am not sure I quite sure I followed that. I do have variable
    > length structures, e.g. some are X parameters long, some are a set of
    > controlling flags. I tried implementing the first example, but I am
    > clearly misunderstanding how to do this.
    >
    > in the .h file
    >
    > typedef struct {
    > FILE *ifp;
    > int num_days;
    > etc...
    > } control_struct;
    >
    > void allocate_structure(structure **);
    >
    > in the .c file
    >
    > int main(int argc, char **argv)
    > {
    > /* Allocate all structures */
    > control_struct *ctrl;
    > allocate_structure(&ctrl);
    > etc...
    >
    > void allocate_structure(structure **s)
    > {
    > if ((*s = malloc(sizeof(*s))) == NULL) {
    > fprintf(stderr, "some msg\n");
    > exit(EXIT_FAILURE);
    > }
    >
    > }
    >
    > it says it doesn't know what 'structure' is when it compiles. I must
    > be misunderstanding as this is what I didn't get, i.e. how to pass the
    > structure, what you call it when you pass it to the function.


    It sounds like you are looking for C++ style templates, which C lacks.

    In C, you would have to resort to a macro. Something like

    #define ALLOCATE_STRUCTURE( s ) \
    if ((s = malloc(sizeof(*s))) == NULL) { \
    fprintf(stderr, "some msg\n"); \
    exit(EXIT_FAILURE); } \


    --
    Ian Collins
     
    Ian Collins, Mar 20, 2012
    #5
  6. I have never used c++ so i am not sure what a c++ style template is,
    but perhaps it is because I have been using a lot of python recently.
    What you suggested works fine. Ideally what I was trying to do was
    move all the structure allocation into a function so the main function
    read a little cleaner. Your suggestion certainly helps, thanks.
     
    Martin De Kauwe, Mar 20, 2012
    #6
  7. Martin De Kauwe <> writes:

    > Sorry I am not sure I quite sure I followed that. I do have variable
    > length structures, e.g. some are X parameters long, some are a set of
    > controlling flags. I tried implementing the first example, but I am
    > clearly misunderstanding how to do this.
    >
    > in the .h file
    >
    > typedef struct {
    > FILE *ifp;
    > int num_days;
    > etc...
    > } control_struct;
    >
    > void allocate_structure(structure **);
    >
    > in the .c file
    >
    > int main(int argc, char **argv)
    > {
    > /* Allocate all structures */
    > control_struct *ctrl;
    > allocate_structure(&ctrl);
    > etc...
    >
    > void allocate_structure(structure **s)
    > {
    > if ((*s = malloc(sizeof(*s))) == NULL) {


    Note: type here. Corrected in my version below.

    > fprintf(stderr, "some msg\n");
    > exit(EXIT_FAILURE);
    > }
    >
    > }
    >
    > it says it doesn't know what 'structure' is when it compiles.


    On the surface it looks like you simply did not update Ian's example to use
    your types. He wrote "void allocate_structure(structure **s)" but that
    was a generic example. You'd have to use your own type:

    void allocate_structure(constrol_struct **s)
    {
    if ((*s = malloc(sizeof **s)) == NULL) {
    fprintf(stderr, "some msg\n");
    exit(EXIT_FAILURE);
    }
    }

    Note the correction to sizeof **s rather than sizeof *s.

    > be misunderstanding as this is what I didn't get, i.e. how to pass the
    > structure, what you call it when you pass it to the function.


    Out of interest, why do you want to it this way? I usually prefer the
    functional "return the pointer" style if it is available,

    --
    Ben.
     
    Ben Bacarisse, Mar 20, 2012
    #7
  8. Martin De Kauwe

    ImpalerCore Guest

    On Mar 19, 10:32 pm, Martin De Kauwe <> wrote:
    > Hi,
    >
    > I currently allocate a series of structures...
    >
    > in the .h file
    >
    > typedef struct {
    >     FILE *in_fp;
    >     etc....
    >
    > } control_struct;
    >
    > then in the main func:
    >
    > control_struct *ctrl;
    > if ((ctrl = malloc(sizeof(control_struct))) == NULL) {
    >     fprintf(stderr, "control structure: Not allocated enough memory
    > \n");
    >     exit(EXIT_FAILURE);
    >
    > }
    >
    > I would like to write my own generic function to take the malloc
    > section to tidy up the code (as I have a number of structures to
    > allocate), i.e. so instead in the main I would have something like
    >
    > allocate_structure(&ctrl);
    >
    > and
    >
    > void allocate_structure(structure *s) {
    >     if ((s = malloc(sizeof(structure))) == NULL) {
    >         fprintf(stderr, "Structure: Not allocated enough memory\n");
    >         exit(EXIT_FAILURE);
    >     }
    >
    > }
    >
    > But I am not sure how to pass the structure when it is unallocated,
    > i.e. how to set up the function declarations.
    >
    > Any assistance would be very helpful


    I prefer to use the same style as malloc to get an allocated block of
    memory. In the same way, I also prefer to keep error handling out of
    the allocation function, relying on checking NULL to determine if
    there was an error.

    \code
    control_struct* cs_alloc( void )
    {
    control_struct* cs = NULL;

    cs = malloc( sizeof (control_struct) );
    if ( cs ) {
    /* Any necessary initialization in here. */
    }

    return cs;
    }
    \endcode

    You can change the style of allocation by writing a macro that takes a
    type parameter instead of a size parameter.

    \code
    /*!
    * \brief Allocate an array of objects by their type.
    * \param type The object type.
    * \param n The number of objects to allocate.
    * \return A pointer to the allocated memory, or \c NULL if the
    * requested allocation failed.
    */
    #define c_new( type, n ) (malloc( sizeof (type) * (size_t)(n) ))
    \endcode

    This is just an allocation style that accents the 'type' rather than
    the type neutral 's = malloc(sizeof *s)'. Preferences vary.

    As you write more code, you'll find that you develop a particular
    style of structured error handling. You can often create a macro that
    wraps your style and use that macro everywhere. The bonus is that if
    you ever change your style, you often only have to do it in one place,
    not everywhere.

    \code
    /* __func__ is standard C in C99 and higher */
    #if !defined(__STDC_VERSION__) /* __STDC_VERSION__ defined in C99 */
    # if (defined(__GNUC__) && __GNUC__ >= 2) || defined(_WIN32) ||
    defined(__WIN32__)
    # define __func__ ((const char*) __FUNCTION__)
    # else
    # define __func__ ((const char*) "")
    # endif
    #endif

    void my_default_report_handler( const char* msg,
    const char* file,
    int line,
    const char* func )
    {
    /* In my case, if I don't have support for __func__, I define
    it above to a string of "". */
    if ( *func != '\0' )
    {
    (void)fprintf( stderr, "%s, file %s, line %d, function %s\n",
    msg, file, line, func );
    }
    else
    {
    (void)fprintf( stderr, "%s, file %s, line %d\n",
    msg, file, line );
    }
    }

    #define c_return_value_if_fail( expr, msg, val ) \
    do \
    { \
    if ( expr ) {} \
    else \
    { \
    my_default_report_handler( msg, __FILE__, \
    __LINE__, __func__ ); \
    return (val); \
    } \
    } while (0)
    \endcode

    With that machinery in place, you can do the following if you wish.

    \code
    int main( void )
    {
    control_struct* cs;

    cs = c_new( control_struct, 1 );
    c_return_value_if_fail( cs != NULL,
    "Structure: Not allocated enough memory",
    EXIT_FAILURE );
    free( cs );

    return 0;
    }
    \endcode

    The 'my_default_report_handler' function can be customized however you
    wish. You can add a parameter for '#expr', log messages to a file
    instead of stderr, inject a timestamp, make it a no-op if 'msg ==
    NULL', popup an error dialog in Windows, ... whatever you want.

    You can have also have a c_return_if_fail( expr, msg ) that just
    returns instead of returning a value for functions that have 'void' as
    the return type. The 'c_return_value_if_fail' macro was inspired from
    GLib. Just some ideas to percolate on.

    Best regards,
    John D.
     
    ImpalerCore, Mar 20, 2012
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alfonso Morra
    Replies:
    11
    Views:
    728
    Emmanuel Delahaye
    Sep 24, 2005
  2. Ken
    Replies:
    24
    Views:
    3,896
    Ben Bacarisse
    Nov 30, 2006
  3. chris
    Replies:
    6
    Views:
    1,006
    chris
    Oct 28, 2005
  4. Replies:
    44
    Views:
    1,417
    Army1987
    Jun 28, 2007
  5. Bjarke Hammersholt Roune
    Replies:
    14
    Views:
    1,207
    Bjarke Hammersholt Roune
    Mar 6, 2011
Loading...

Share This Page