nested structures and initialization

Discussion in 'C Programming' started by Sheldon, Oct 31, 2007.

  1. Sheldon

    Sheldon Guest

    Hi,

    Can anyone help with this problem with setting up nested structures
    and initializing them for use.
    I have created several structs and placed them in a super struct that
    I will then pass to some functions. I have defined them in the
    following manner:

    typedef struct trans Transient;
    typedef struct sats Satellites;
    typedef struct data Data;
    typedef struct super Super;

    struct data {
    float table_10[ROW*COL];
    float table_20[ROW*COL];
    float table_30[ROW*COL];
    float table_40[ROW*COL];
    float table_50[ROW*COL];
    float table_60[ROW*COL];
    float procent_amsu;
    };

    struct trans {
    char operationalfile[MAXSTR_LENGTH];
    char tunedfile[MAXSTR_LENGTH];
    char radarfile[MAXSTR_LENGTH];
    float amsu_flag[ARRAYSIZE];
    float radar[ARRAYSIZE];
    float pcpn1[ARRAYSIZE];
    float pcpn2[ARRAYSIZE];
    float pcpn3[ARRAYSIZE];
    };

    struct sats {
    Data *pN18;
    Data *pN17;
    Data *pN16;
    Data *pN15;
    Data *pM02;
    };

    struct super {
    Transient *TR;
    Satellites *Sp;
    Satellites *Su;
    Satellites *Au;
    Satellites *Wi;
    };

    Super* InitStruct(void);

    Now when I try to intialize the structure I get a bunch of errors. The
    InitStruct functions looks like this:

    int main() {

    Super *sptr;
    /* initializing the super structure */
    sptr = InitStruct();
    if (sptr == NULL) {
    fprintf(stderr,"Failed to initialize nested structure!\n");
    exit(EXIT_FAILURE);
    } else {
    printf("Structure now initialized!\n");
    }
    return 1;
    }

    Super *InitStruct(void) {

    Super *sptr=NULL;

    if(!(sptr=malloc(sizeof(Super)))) {
    return NULL;
    }
    sptr->TR->operationalfile=NULL;
    sptr->TR->tunedfile=NULL;
    sptr->TR->radarfile=NULL;
    sptr->TR->amsu_flag={0.0};
    sptr->TR->radar={0.0};
    sptr->TR->pcpn1={0.0};
    sptr->TR->pcpn2={0.0};
    sptr->TR->pcpn3={0.0};

    sptr->Sp->N18->table_10={0.0};
    sptr->Sp->N18->table_20={0.0};
    sptr->Sp->N18->table_30={0.0};
    sptr->Sp->N18->table_40={0.0};
    sptr->Sp->N18->table_50={0.0};
    sptr->Sp->N18->table_60={0.0};
    sptr->Sp->N18->procent_amsu = 0.0;

    sptr->Sp->N17->table_10={0.0};
    sptr->Sp->N17->table_20={0.0};
    sptr->Sp->N17->table_30={0.0};
    sptr->Sp->N17->table_40={0.0};
    sptr->Sp->N17->table_50={0.0};
    sptr->Sp->N17->table_60={0.0};
    sptr->Sp->N17->procent_amsu = 0.0;
    .....

    }

    The errors begin with these:

    error: incompatible types in assignment
    error: incompatible types in assignment
    error: incompatible types in assignment
    error: parse error before '{' token
    error: parse error before '{' token

    and keeps on going.

    Could some please render some help in doing this correctly?

    Any help is truly appreciated.
    /S
    Sheldon, Oct 31, 2007
    #1
    1. Advertising

  2. Sheldon

    Keith Willis Guest

    On Wed, 31 Oct 2007 09:18:29 -0000, Sheldon <>
    wrote:

    >Can anyone help with this problem with setting up nested structures
    >and initializing them for use.
    >I have created several structs and placed them in a super struct that
    >I will then pass to some functions. I have defined them in the
    >following manner:


    <snip>

    >typedef struct super Super;


    <snip>
    >struct super {
    > Transient *TR;
    > Satellites *Sp;
    > Satellites *Su;
    > Satellites *Au;
    > Satellites *Wi;
    >};


    <snip>

    >Super *InitStruct(void) {
    >
    >Super *sptr=NULL;
    >
    > if(!(sptr=malloc(sizeof(Super)))) {
    > return NULL;
    > }


    <snip remainder>

    Well the first thing that leaps out is that you've allocated space for
    a "struct super", which is simply five pointers. Nowhere do you
    allocate the memory that those pointers point at. I'm not even going
    to try and see what else is wrong :)
    --
    PGP key ID 0xEB7180EC
    Keith Willis, Oct 31, 2007
    #2
    1. Advertising

  3. Sheldon

    Sheldon Guest

    On 31 Okt, 10:44, Keith Willis <> wrote:
    > On Wed, 31 Oct 2007 09:18:29 -0000, Sheldon <>
    > wrote:
    >
    > >Can anyone help with this problem with setting up nested structures
    > >and initializing them for use.
    > >I have created several structs and placed them in a super struct that
    > >I will then pass to some functions. I have defined them in the
    > >following manner:

    >
    > <snip>
    >
    > >typedef struct super Super;

    >
    > <snip>
    >
    > >struct super {
    > > Transient *TR;
    > > Satellites *Sp;
    > > Satellites *Su;
    > > Satellites *Au;
    > > Satellites *Wi;
    > >};

    >
    > <snip>
    >
    > >Super *InitStruct(void) {

    >
    > >Super *sptr=NULL;

    >
    > > if(!(sptr=malloc(sizeof(Super)))) {
    > > return NULL;
    > > }

    >
    > <snip remainder>
    >
    > Well the first thing that leaps out is that you've allocated space for
    > a "struct super", which is simply five pointers. Nowhere do you
    > allocate the memory that those pointers point at. I'm not even going
    > to try and see what else is wrong :)
    > --
    > PGP key ID 0xEB7180EC


    Ok, fair enough. How would you do it then? Let's say a 3 tier struct?
    Can you give an example that I can expland on?

    /S
    Sheldon, Oct 31, 2007
    #3
  4. Sheldon

    James Kuyper Guest

    Sheldon wrote:
    > Hi,
    >
    > Can anyone help with this problem with setting up nested structures
    > and initializing them for use.
    > I have created several structs and placed them in a super struct that
    > I will then pass to some functions. I have defined them in the
    > following manner:
    >
    > typedef struct trans Transient;
    > typedef struct sats Satellites;
    > typedef struct data Data;
    > typedef struct super Super;
    >
    > struct data {
    > float table_10[ROW*COL];
    > float table_20[ROW*COL];
    > float table_30[ROW*COL];
    > float table_40[ROW*COL];
    > float table_50[ROW*COL];
    > float table_60[ROW*COL];
    > float procent_amsu;
    > };


    Why do you define 6 separate on-dimensional tables, rather than a single
    table with a leading dimension of 6? I suspect it will simplify the code
    that uses this structure.

    I would also recommend combining those typedefs with the corresponding
    struct declarations:

    typedef struct data {....} Data;

    I find that easier to understand; YMMV.

    > struct trans {
    > char operationalfile[MAXSTR_LENGTH];
    > char tunedfile[MAXSTR_LENGTH];
    > char radarfile[MAXSTR_LENGTH];
    > float amsu_flag[ARRAYSIZE];
    > float radar[ARRAYSIZE];
    > float pcpn1[ARRAYSIZE];
    > float pcpn2[ARRAYSIZE];
    > float pcpn3[ARRAYSIZE];
    > };


    Same comment about the pcpn family.

    > struct sats {
    > Data *pN18;
    > Data *pN17;
    > Data *pN16;
    > Data *pN15;
    > Data *pM02;
    > };
    >
    > struct super {
    > Transient *TR;
    > Satellites *Sp;
    > Satellites *Su;
    > Satellites *Au;
    > Satellites *Wi;
    > };
    >
    > Super* InitStruct(void);
    >
    > Now when I try to intialize the structure I get a bunch of errors. The
    > InitStruct functions looks like this:
    >
    > int main() {
    >
    > Super *sptr;
    > /* initializing the super structure */
    > sptr = InitStruct();
    > if (sptr == NULL) {
    > fprintf(stderr,"Failed to initialize nested structure!\n");
    > exit(EXIT_FAILURE);
    > } else {
    > printf("Structure now initialized!\n");
    > }
    > return 1;
    > }
    >
    > Super *InitStruct(void) {


    That's a bad naming choice. InitSuper would be better. In general, you
    might have quite a lot of different structures to initialize. In this
    particular case, you have two of them, which is enough to justify not
    naming either function "InitStruct".

    > Super *sptr=NULL;
    >
    > if(!(sptr=malloc(sizeof(Super)))) {
    > return NULL;
    > }


    At this point, none of the pointer members of *sptr have been
    initialized. Any use of the value of those pointers has undefined
    behavior. You need to allocate memory for each of the pointed at
    objects. Note: with this data structure you're going to have to make
    LOTS of separate memory allocations. If any one of those fails, then all
    of the allocations that succeeded should be free()d. This can get very
    complicated very fast. I avoid building structures like this, for
    precisely that reason. Therefore, the solution I use below is not the
    result of lots of experience with this kind of thing, but it's a lot
    better than other techniques I've seen used:

    bool successful = true;
    // Initialize to make sure that we can free() them without worrying
    // about whether they have been allocated:
    sptr->TR = NULL;
    sptr->Sp = NULL;
    // Similarly for other pointer members


    if(!(sptr->TR = malloc(sizeof Transient)) ||
    !(sptr->Sp = malloc(sizeof Satellites)) ||
    // Similarly for other pointer members
    ){
    successful = false;
    }

    ....
    > sptr->TR->amsu_flag={0.0};


    The curly brackets are a syntax error in this context. I think you are
    thinking of initialization syntax, but that doesn't apply to dynamically
    allocated memory. You'll have to write a loop to initialize that array.
    You'll be doing a lot of this, so I'd recommend creating a subroutine
    analogous to memset() which works on floats rather than unsigned char.

    If you use calloc() instead of malloc(), or use memset() after malloc(),
    on many implementations the floats will be properly initialized. That's
    because floating point formats which use a representation for 0.0 that
    has all of its bits set to 0 are fairly common. However, that's not
    guaranteed by the C standard, so you should not use that approach in
    code that needs to be portable.

    At this point, none of the pointer members of sptr->Sp have been
    initialized. Any attempt to use their current value has undefined
    behavior. You need to allocate memory for each one, just as I described
    above for the pointer members of sptr itself. You'll need to do this
    many times, so I recommend writing as subroutine to handle it. Later on,
    you'll need to deallocate all of that memory; again, you should use a
    subroutine. I'll need to refer to those routines down below, so I'll
    call them InitSatellite() and FreeSatellite(). Note: if the argument
    passed to FreeSatellite is null, it should return without doing
    anything, the same way that free() itself does.

    Remember to set successful = false if any of the InitSatellite() calls
    fails.

    This code should (with appropriate re-writes) be part of InitSatellite():

    ....
    > sptr->Sp->N18->table_10={0.0};

    ....

    if(!successful)
    { // Free everything, regardless of whether it's been allocated.
    free(sptr->TR);
    FreeSatellite(sptr->Sp);
    free(sptr->Sp);
    // Similarly for other Satellites* members.
    free(sptr);
    return NULL;
    }

    return sptr;
    // Your original did not appear to include a return statement?
    > }
    James Kuyper, Oct 31, 2007
    #4
  5. Sheldon

    Mark Bluemel Guest

    Sheldon wrote:
    > Hi,
    >
    > Can anyone help with this problem with setting up nested structures
    > and initializing them for use.
    > I have created several structs and placed them in a super struct that
    > I will then pass to some functions. I have defined them in the
    > following manner:
    >
    > typedef struct trans Transient;
    > typedef struct sats Satellites;
    > typedef struct data Data;
    > typedef struct super Super;
    >
    > struct data {
    > float table_10[ROW*COL];
    > float table_20[ROW*COL];
    > float table_30[ROW*COL];
    > float table_40[ROW*COL];
    > float table_50[ROW*COL];
    > float table_60[ROW*COL];
    > float procent_amsu;
    > };
    >
    > struct trans {
    > char operationalfile[MAXSTR_LENGTH];
    > char tunedfile[MAXSTR_LENGTH];
    > char radarfile[MAXSTR_LENGTH];
    > float amsu_flag[ARRAYSIZE];
    > float radar[ARRAYSIZE];
    > float pcpn1[ARRAYSIZE];
    > float pcpn2[ARRAYSIZE];
    > float pcpn3[ARRAYSIZE];
    > };
    >
    > struct sats {
    > Data *pN18;
    > Data *pN17;
    > Data *pN16;
    > Data *pN15;
    > Data *pM02;
    > };
    >
    > struct super {
    > Transient *TR;
    > Satellites *Sp;
    > Satellites *Su;
    > Satellites *Au;
    > Satellites *Wi;
    > };
    >
    > Super* InitStruct(void);
    >
    > Now when I try to intialize the structure I get a bunch of errors. The
    > InitStruct functions looks like this:
    >
    > int main() {
    >
    > Super *sptr;
    > /* initializing the super structure */
    > sptr = InitStruct();
    > if (sptr == NULL) {
    > fprintf(stderr,"Failed to initialize nested structure!\n");
    > exit(EXIT_FAILURE);
    > } else {
    > printf("Structure now initialized!\n");
    > }
    > return 1;
    > }
    >
    > Super *InitStruct(void) {
    >
    > Super *sptr=NULL;
    >
    > if(!(sptr=malloc(sizeof(Super)))) {
    > return NULL;
    > }


    if (!(sptr->TR = malloc(sizeof(Transient))) {
    return NULL;
    } /* and for the rest of the substructures */

    > sptr->TR->operationalfile=NULL;
    > sptr->TR->tunedfile=NULL;
    > sptr->TR->radarfile=NULL;
    > sptr->TR->amsu_flag={0.0};


    You can't in general assign arrays - this syntax is allowed in
    initializers only, I think.

    This should work though (I think) :-

    sptr->TR->amsu_flag=0;

    repeat as needed...

    Personally I'd have been inclined to go encapsulated and have functions
    to return initialized substructures, I think. (Too much exposure to OO?)
    Mark Bluemel, Oct 31, 2007
    #5
  6. Sheldon

    James Kuyper Guest

    Mark Bluemel wrote:
    ....
    > This should work though (I think) :-
    >
    > sptr->TR->amsu_flag=0;


    amsu_flag is an array of floats. Therefore it's not a modifiable lvalue
    (6.3.2.1p1), so it can't be the left operand of an assignment operator
    (6.5.16p2).
    James Kuyper, Oct 31, 2007
    #6
  7. Sheldon

    Mark Bluemel Guest

    James Kuyper wrote:
    > Mark Bluemel wrote:
    > ...
    >> This should work though (I think) :-
    >>
    >> sptr->TR->amsu_flag=0;

    >
    > amsu_flag is an array of floats. Therefore it's not a modifiable lvalue
    > (6.3.2.1p1), so it can't be the left operand of an assignment operator
    > (6.5.16p2).


    I did wonder, but it compiled (gcc) even with strict options...
    Mark Bluemel, Oct 31, 2007
    #7
  8. Sheldon

    Sheldon Guest

    On 31 Okt, 12:44, Mark Bluemel <> wrote:
    > Sheldon wrote:
    > > Hi,

    >
    > > Can anyone help with this problem with setting up nested structures
    > > and initializing them for use.
    > > I have created several structs and placed them in a super struct that
    > > I will then pass to some functions. I have defined them in the
    > > following manner:

    >
    > > typedef struct trans Transient;
    > > typedef struct sats Satellites;
    > > typedef struct data Data;
    > > typedef struct super Super;

    >
    > > struct data {
    > > float table_10[ROW*COL];
    > > float table_20[ROW*COL];
    > > float table_30[ROW*COL];
    > > float table_40[ROW*COL];
    > > float table_50[ROW*COL];
    > > float table_60[ROW*COL];
    > > float procent_amsu;
    > > };

    >
    > > struct trans {
    > > char operationalfile[MAXSTR_LENGTH];
    > > char tunedfile[MAXSTR_LENGTH];
    > > char radarfile[MAXSTR_LENGTH];
    > > float amsu_flag[ARRAYSIZE];
    > > float radar[ARRAYSIZE];
    > > float pcpn1[ARRAYSIZE];
    > > float pcpn2[ARRAYSIZE];
    > > float pcpn3[ARRAYSIZE];
    > > };

    >
    > > struct sats {
    > > Data *pN18;
    > > Data *pN17;
    > > Data *pN16;
    > > Data *pN15;
    > > Data *pM02;
    > > };

    >
    > > struct super {
    > > Transient *TR;
    > > Satellites *Sp;
    > > Satellites *Su;
    > > Satellites *Au;
    > > Satellites *Wi;
    > > };

    >
    > > Super* InitStruct(void);

    >
    > > Now when I try to intialize the structure I get a bunch of errors. The
    > > InitStruct functions looks like this:

    >
    > > int main() {

    >
    > > Super *sptr;
    > > /* initializing the super structure */
    > > sptr = InitStruct();
    > > if (sptr == NULL) {
    > > fprintf(stderr,"Failed to initialize nested structure!\n");
    > > exit(EXIT_FAILURE);
    > > } else {
    > > printf("Structure now initialized!\n");
    > > }
    > > return 1;
    > > }

    >
    > > Super *InitStruct(void) {

    >
    > > Super *sptr=NULL;

    >
    > > if(!(sptr=malloc(sizeof(Super)))) {
    > > return NULL;
    > > }

    >
    > if (!(sptr->TR = malloc(sizeof(Transient))) {
    > return NULL;
    > } /* and for the rest of the substructures */
    >
    > > sptr->TR->operationalfile=NULL;
    > > sptr->TR->tunedfile=NULL;
    > > sptr->TR->radarfile=NULL;
    > > sptr->TR->amsu_flag={0.0};

    >
    > You can't in general assign arrays - this syntax is allowed in
    > initializers only, I think.
    >
    > This should work though (I think) :-
    >
    > sptr->TR->amsu_flag=0;
    >
    > repeat as needed...
    >
    > Personally I'd have been inclined to go encapsulated and have functions
    > to return initialized substructures, I think. (Too much exposure to OO?)- Dölj citerad text -
    >
    > - Visa citerad text -



    Hi,

    Thanks for your input. I took your advice and redesigned the script.
    Now things are done in smaller steps. But I still get a persistent
    error. Here are the new header and source files:
    <snip>

    typedef struct {
    float thres_tables[THRESHOLDS][ROW*COL];
    float procent_amsu;
    } Data;

    typedef struct {
    char operationalfile[MAXSTR_LENGTH];
    char tunedfile[MAXSTR_LENGTH];
    char radarfile[MAXSTR_LENGTH];
    float amsu_flag[ARRAYSIZE];
    double variables[COMP_VAR][ARRAYSIZE];
    Data* satid;
    } SUPER;

    SUPER* NewSatellite(void);

    /* pointers for sub strings */
    char *p;
    int counter;
    SUPER *retv=NULL;

    /* initializing the super structure */
    retv = NewSatellite();
    if (retv == NULL) {
    fprintf(stderr,"Failed to initialize nested structure!\n");
    exit(EXIT_FAILURE);
    } else {
    printf("Structure now initialized!\n");
    }
    /* read the file list one at a time */
    file = fopen(datafile,"r");
    if (file == NULL) {
    fprintf(stderr,"Error: can't open file %s\n", datafile);
    exit(EXIT_FAILURE);
    } else {
    printf("File successfully opened. Reading line by line...\n");
    j = 0;
    while (fgets(line,MAXLINE_LENGTH,file) != NULL) {
    printf("Line %d\t%s\n",++j,line);
    /* cutting the strings using delimiter ' ' */
    p = strtok(line," ");
    counter = 0;
    while (p != NULL) {
    if (counter == 0) strcpy(retv->tunedfile,p);
    p = strtok(NULL," ");
    printf("Sub string: %s\n",retv->tunedfile);
    counter++;
    }
    } /* end while */
    printf("EOF reached. Closing the file...\n");
    fclose(file);
    } /* else section if file is open without problem */
    return 1;
    } /* end main */

    /* Initialize the structure */
    SUPER* NewSatellite(void) {

    int i,j;
    SUPER *retv = NULL;

    if ((retv = malloc(sizeof(SUPER))) == NULL) {
    fprintf(stderr,"Failed to allocate memory for structure!\n");
    exit(EXIT_FAILURE);
    }

    retv->operationalfile = NULL;
    retv->tunedfile = NULL;
    retv->radarfile = NULL;
    retv->satid->procent_amsu = 0.0;
    for (i=0; i < COMP_VAR; i++) {
    for (j = 0; j < ARRAYSIZE; j++) {
    retv->variables[j] = 0.0;
    retv->amsu_flag[j] = 0.0;
    }
    }
    for (i=0; i < THRESHOLDS; i++) {
    for (j = 0; j < ROW*COL; j++) {
    retv->satid->thres_tables[j] = 0.0;
    }
    }
    return retv;
    };

    but the error remains:
    c: In function `main':
    c:20: warning: unused variable `i'
    c: In function `NewSatellite':
    c:73: error: incompatible types in assignment
    c:74: error: incompatible types in assignment
    c:75: error: incompatible types in assignment
    c:76: warning: statement with no effect


    What I am missing here?

    /S
    Sheldon, Oct 31, 2007
    #8
  9. Sheldon

    Keith Willis Guest

    On Wed, 31 Oct 2007 13:11:09 -0000, Sheldon <>
    wrote:
    <much snippage>
    >
    > retv->operationalfile = NULL;
    > retv->tunedfile = NULL;
    > retv->radarfile = NULL;

    <more snippage>

    >c: In function `NewSatellite':
    >c:73: error: incompatible types in assignment
    >c:74: error: incompatible types in assignment
    >c:75: error: incompatible types in assignment
    >c:76: warning: statement with no effect


    I told you in the email I sent you that your initialisation of these
    strings was nonsense. You are trying to assign the value NULL to a
    variable of type array-of-char. You need to set the first character
    of the array-of-char to the value '\0', thus:

    retv->operationalfile[0] = '\0';

    Alternatively, initialise the entire string to zeros (overkill):

    memset(retv->operationalfile, 0, sizeof retv->operationalfile);

    >What I am missing here?


    Clues?
    --
    PGP key ID 0xEB7180EC
    Keith Willis, Oct 31, 2007
    #9
    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. tweak
    Replies:
    14
    Views:
    2,779
    Eric Sosman
    Jun 11, 2004
  2. Alfonso Morra
    Replies:
    11
    Views:
    713
    Emmanuel Delahaye
    Sep 24, 2005
  3. Jess
    Replies:
    23
    Views:
    926
  4. Replies:
    5
    Views:
    1,977
    Arne Mertz
    Mar 26, 2009
  5. Taras_96
    Replies:
    3
    Views:
    585
    Michael Tsang
    Oct 30, 2009
Loading...

Share This Page