nested struct that grow in some cases

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Sheldon

    nested struct that grow in some cases

    Hi,

    I have a unique case where I need an array of structs that grows and
    within this array is another struct that grows in some cases. I'm
    having trouble allocating memory. Since I have never done this before,
    I'm sure it's a rookie mistake but I cannot seem to find it. Can
    someone render some assistance please?

    struct Fpos {
    grib_handle *h;
    char level[MAX_VAL_LEN];
    };

    struct Parameter {
    double *lvlpress;
    double *geomethgt;
    double *ab_array;
    double *pottemp;
    int nlev;
    size_t size;
    char parameter[MAX_VAL_LEN];
    unsigned char **GribNameValue s;
    struct Fpos **filepos;
    } **Darray;


    Darray = (struct Parameter **)realloc(Darr ay,(num + 1)*sizeof(struc t
    Parameter *));
    /* allocate memory for one struct Parameter */
    Darray[num] = (struct Parameter *)smalloc(sizeo f(struct Parameter));
    /* same as above but for the nested struct */
    Darrray[num]->filepos = (struct Fpos **)realloc(file pos,(lvlnum +
    1)*sizeof(struc t Fpos *));
    Darrray[num]->filepos[lvlnum] = (struct Fpos *)smalloc(sizeo f(struct
    Fpos));

    When I compile, I get an error saying that filepos is not declared and
    is new.

    How should this be done properly?

    /M

  • MisterE

    #2
    Re: nested struct that grow in some cases

    When I compile, I get an error saying that filepos is not declared and
    is new.
    >
    How should this be done properly?
    You need to post more code. You don't declare Darray at all, you only set
    Darray as a tag.
    So Darray = (struct ..... line should be telling you that Darray is not
    declared.
    Filepos is not declared either:
    Darrray[num]->filepos = (struct Fpos **)realloc(file pos, <--- not declared
    variable

    post your code properly not just cut lines


    Comment

    • Ben Bacarisse

      #3
      Re: nested struct that grow in some cases

      Sheldon <shejo284@gmail .comwrites:
      I have a unique case where I need an array of structs that grows and
      within this array is another struct that grows in some cases. I'm
      having trouble allocating memory. Since I have never done this before,
      I'm sure it's a rookie mistake but I cannot seem to find it. Can
      someone render some assistance please?
      You have a few typos. Did you post actual code?
      struct Fpos {
      grib_handle *h;
      char level[MAX_VAL_LEN];
      };
      >
      struct Parameter {
      double *lvlpress;
      double *geomethgt;
      double *ab_array;
      double *pottemp;
      int nlev;
      size_t size;
      char parameter[MAX_VAL_LEN];
      unsigned char **GribNameValue s;
      struct Fpos **filepos;
      } **Darray;
      >
      >
      Darray = (struct Parameter **)realloc(Darr ay,(num + 1)*sizeof(struc t
      Parameter *));
      Beware. This is wrong unless Darray has been set to NULL (or points
      previously allocated memory).

      Life will be simpler is you use the comp.lang.c standard idiom:

      ptr = malloc(how_many * sizeof *ptr);
      /* allocate memory for one struct Parameter */
      Darray[num] = (struct Parameter *)smalloc(sizeo f(struct Parameter));
      /* same as above but for the nested struct */
      Darrray[num]->filepos = (struct Fpos **)realloc(file pos,(lvlnum +
      1)*sizeof(struc t Fpos *));
      Both Darrray (note three 'r's) and filepos (the one after realloc) are
      new undeclared names here. One is a typo, but the other is just
      wrong. You probably meant ... realloc(Darray[num]->filepos, ...
      Darrray[num]->filepos[lvlnum] = (struct Fpos *)smalloc(sizeo f(struct
      Fpos));
      Three 'r's again and smalloc is an odd name.
      When I compile, I get an error saying that filepos is not declared and
      is new.
      >
      How should this be done properly?
      Do you really need pointers of arrays of pointers for both Darray and
      the internal filepos? Dynamic arrays are often just represented by
      pointers to the first element.

      --
      Ben.

      Comment

      • Ben Bacarisse

        #4
        Re: nested struct that grow in some cases

        "MisterE" <MisterE@nimga. comwrites:
        You need to post more code. You don't declare Darray at all, you only set
        Darray as a tag.
        No, he declared it. The struct tag is "Parameter" .

        --
        Ben.

        Comment

        • David Thompson

          #5
          Re: nested struct that grow in some cases

          On Mon, 20 Oct 2008 03:18:29 -0700 (PDT), Sheldon <shejo284@gmail .com>
          wrote:
          Hi,
          >
          I have a unique case where I need an array of structs that grows and
          within this array is another struct that grows in some cases. I'm
          Not actually within. I'd say under or subordinate to each element.
          having trouble allocating memory. Since I have never done this before,
          I'm sure it's a rookie mistake but I cannot seem to find it. Can
          someone render some assistance please?
          >
          struct Fpos {
          grib_handle *h;
          char level[MAX_VAL_LEN];
          };
          >
          struct Parameter {
          double *lvlpress;
          double *geomethgt;
          double *ab_array;
          double *pottemp;
          int nlev;
          size_t size;
          char parameter[MAX_VAL_LEN];
          unsigned char **GribNameValue s;
          struct Fpos **filepos;
          } **Darray;
          >
          >
          Darray = (struct Parameter **)realloc(Darr ay,(num + 1)*sizeof(struc t
          Parameter *));
          /* allocate memory for one struct Parameter */
          Darray[num] = (struct Parameter *)smalloc(sizeo f(struct Parameter));
          These are valid assuming that Darray is initialized to a null pointer
          and num to zero, which will happen automatically if they are defined
          at file scope (or otherwise with static duration). But you should
          check for allocation failure and handle it in some reasonable fashion;
          to do that it may be better to save realloc's return in a temporary
          and check it first before putting it into Darray. And you don't need
          to cast the return of malloc et al., if they are properly declared by
          #include'ing <stdlib.h>, which they must be.

          However, if the number of struct Parameter pointers gets large, on
          most implementations it will be inefficient to realloc up by 1 each
          time, because it will at least sometimes have to copy quadratically
          increasing amounts of data. You might want to do something a little
          more complicated like:
          unsigned long numalloc /* = 0 *(/, numused /* = 0 */;
          struct Parameter ** Darray /* = NULL */;
          ....
          if( numused == /* or >= to be defensive */ numalloc ){
          struct Parameter **temp = realloc (Darray,
          (numalloc=numal loc*3/2+1) * sizeof (struct Parameter *) );
          /* or sizeof *temp, which is equivalent and safe
          and easier to maintain, hence clc-preferred */
          /* personally I usually start with a smallish nonzero number,
          and grow by *2, but that's a little bit more to write */
          if( temp == NULL ) HANDLE ERROR;
          Darray = temp; /* successfully grew */
          }
          /* now there's at least Darray[0..numused] and often more */
          Darray[numused] = smalloc (sizeof *Darray[numused]);
          /* unless smalloc() already handled allocation failure: */
          if( Darray[numused] == NULL ) HANDLE ERROR;
          /* same as above but for the nested struct */
          Darrray[num]->filepos = (struct Fpos **)realloc(file pos,(lvlnum +
          1)*sizeof(struc t Fpos *));
          Darrray[num]->filepos[lvlnum] = (struct Fpos *)smalloc(sizeo f(struct
          Fpos));
          >
          As others have noted, the second filepos here is a variable not a
          struct member. But if you make it the struct member that might not be
          right either. Did smalloc() initialize the space containing it
          suitably? If not, trying to realloc it is Undefined Behavior.
          Note that initializing the space to all-zero-bits isn't guaranteed to
          make the pointer null, although on _most_ systems it does work.
          And smalloc() sounds like a general-purpose routine that doesn't know
          about the contents of what it allocates and in particular where
          pointers are (or can be).

          Plus, your lvlnum is questionable. It can be a separate single
          variable only if all Darray[i] elements have the same 'size' of
          Darray[i]->filepos at all times, and your code as shown doesn't do
          that. If you want say Darray[1]->filepos to grow separately from
          Darray[0]->filepos, you need a separate counter in (or mapped
          one-to-one to) each struct Parameter. You do have .nlev already, whose
          name sounds like it might be intended for this. It similarly must be
          initialized to zero, but for an integer type (not a pointer)
          initializing to all-bits-zero (if smalloc() does that) is OK.

          If you want them all to grow in sync, you need different logic. E.g.:
          - allocate Darray to M pointers and each of those M pointers to a
          struct Parameter with .filepos null (empty); you can do this using
          one-at-a-time logic like the above, or all (or batches) at once
          - (then) allocate each Darray [0..M-1] ->filepos to N pointers and set
          each of those Darray [0..M-1] ->filepos [0..N-1] to a struct Fpos.
          Again you can do these one-at-a-time, in which case you can nest the
          loops either way (for each filepos within in Darray or vice versa), or
          batched in which case the allocations of the pointer space must loop
          over Darray[] (first) but the elements can then nest either way but
          can be merged with the pointer allocation only if Darray-major.

          Other logics are possible. You'd have to explain more about what you
          want to do with (i.e. put into) the resulting data structure.
          When I compile, I get an error saying that filepos is not declared and
          is new.
          >
          How should this be done properly?
          >
          /M
          - formerly david.thompson1 || achar(64) || worldnet.att.ne t

          Comment

          Working...