Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #18885 > unrolled thread

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

Started byMartin De Kauwe <mdekauwe@gmail.com>
First post2012-03-19 19:32 -0700
Last post2012-03-20 07:27 -0700
Articles 8 — 5 participants

Back to article view | Back to comp.lang.c


Contents

  How to write own function to allocation a set of structures? Martin De Kauwe <mdekauwe@gmail.com> - 2012-03-19 19:32 -0700
    Re: How to write own function to allocation a set of structures? Ian Collins <ian-news@hotmail.com> - 2012-03-20 15:50 +1300
    Re: How to write own function to allocation a set of structures? Barry Schwarz <schwarzb@dqel.com> - 2012-03-19 20:14 -0700
      Re: How to write own function to allocation a set of structures? Martin De Kauwe <mdekauwe@gmail.com> - 2012-03-19 23:58 -0700
        Re: How to write own function to allocation a set of structures? Ian Collins <ian-news@hotmail.com> - 2012-03-20 21:13 +1300
          Re: How to write own function to allocation a set of structures? Martin De Kauwe <mdekauwe@gmail.com> - 2012-03-20 02:32 -0700
        Re: How to write own function to allocation a set of structures? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-03-20 13:06 +0000
    Re: How to write own function to allocation a set of structures? ImpalerCore <jadill33@gmail.com> - 2012-03-20 07:27 -0700

#18885 — How to write own function to allocation a set of structures?

FromMartin De Kauwe <mdekauwe@gmail.com>
Date2012-03-19 19:32 -0700
SubjectHow to write own function to allocation a set of structures?
Message-ID<354bb461-708b-4ce5-99ad-ab0b37872797@x10g2000pbi.googlegroups.com>
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.

[toc] | [next] | [standalone]


#18888

FromIan Collins <ian-news@hotmail.com>
Date2012-03-20 15:50 +1300
Message-ID<9sq9k5FuerU3@mid.individual.net>
In reply to#18885
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

[toc] | [prev] | [next] | [standalone]


#18889

FromBarry Schwarz <schwarzb@dqel.com>
Date2012-03-19 20:14 -0700
Message-ID<rmsfm7p8u92iun6n37sn6m6qp7ihabvnl3@4ax.com>
In reply to#18885
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
<mdekauwe@gmail.com> 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

[toc] | [prev] | [next] | [standalone]


#18892

FromMartin De Kauwe <mdekauwe@gmail.com>
Date2012-03-19 23:58 -0700
Message-ID<8223ddb2-04c4-435e-9e6a-4c56c3f0cba9@vy8g2000pbc.googlegroups.com>
In reply to#18889
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.

[toc] | [prev] | [next] | [standalone]


#18893

FromIan Collins <ian-news@hotmail.com>
Date2012-03-20 21:13 +1300
Message-ID<9sqshlFc6rU1@mid.individual.net>
In reply to#18892
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

[toc] | [prev] | [next] | [standalone]


#18897

FromMartin De Kauwe <mdekauwe@gmail.com>
Date2012-03-20 02:32 -0700
Message-ID<d131016a-eacf-45c4-b7c5-2b81a3372ec8@ow8g2000pbc.googlegroups.com>
In reply to#18893
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.

[toc] | [prev] | [next] | [standalone]


#18902

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2012-03-20 13:06 +0000
Message-ID<0.c7863358bf1d9ffca8ac.20120320130601GMT.874ntje81y.fsf@bsb.me.uk>
In reply to#18892
Martin De Kauwe <mdekauwe@gmail.com> 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.

[toc] | [prev] | [next] | [standalone]


#18903

FromImpalerCore <jadill33@gmail.com>
Date2012-03-20 07:27 -0700
Message-ID<976bdf97-4076-4fac-af65-ab5fb105b5b2@v2g2000vbx.googlegroups.com>
In reply to#18885
On Mar 19, 10:32 pm, Martin De Kauwe <mdeka...@gmail.com> 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.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web