structs and dynamic memory allocation

Discussion in 'C Programming' started by Roman Hartmann, Nov 4, 2003.

  1. hello,
    I do have a question regarding structs. I have a struct (profil) which
    has a pointer to another struct (point). The struct profil stores the
    coordinates of points.
    The problem is that I don't know how many points
    there will be in every struct in the end, so I have to allocate memory
    dynamically for
    them and can't use an array of fixed size, unfortunately.

    I would like to know if there is a better way to access struct members (the
    points).
    Accessing struct members with p1->p2->x seems rather ugly and unsafe.

    Below is a stripped down version of the program, just to get an idea what
    I'm trying to do. I'm aware that this is not a pure ANSI C definition
    question, but I couldn't find any help to this special problem neither in
    K&R nor in the FAQ. So I apreciate every hint.

    Best Regards
    Roman

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

    /* struct with points, used by struct profil */

    struct point
    {
    double x;
    double y;
    };

    struct profil
    {
    struct point *pt;
    struct profil *previous;
    struct profil *next;
    };

    int main(void)
    {
    int n;

    struct profil *p1;
    struct profil *begin;

    n=2; /* only to allocate memory for this example */

    if((p1=(struct profil *) malloc(sizeof(struct profil)))==NULL)
    {
    printf("\nMemory allocation failed\n");
    return 1;
    }

    begin=p1;

    if((p1->pt=(struct point *) malloc(n*sizeof(struct point)))==NULL)
    {
    printf("\nMemory allocation failed\n");
    return 1;
    }

    /* put some information into the struct */

    p1->pt->x=1265.75;
    p1->pt->y=150.73;

    p1->pt++; /* ugly, I know. Is there a better way to do this? */

    p1->pt->x=550.55;
    p1->pt->y=350.33;

    p1->pt--;

    /* do something with the structs */
    /* instead of printing results, I print the structs out */

    printf("\nStrukt 1: %f\n", p1->pt->x);
    printf("\nStrukt 1: %f\n", p1->pt->y);

    p1->pt++;

    printf("\nStrukt 2: %f\n", p1->pt->x);
    printf("\nStrukt 2: %f\n", p1->pt->y);

    return 0;
    }
    Roman Hartmann, Nov 4, 2003
    #1
    1. Advertising

  2. Roman Hartmann wrote:
    > I would like to know if there is a better way to access struct members
    > (the points).
    > Accessing struct members with p1->p2->x seems rather ugly and unsafe.
    >

    [. . .]
    >
    > /* struct with points, used by struct profil */
    >
    > struct point
    > {
    > double x;
    > double y;
    > };
    >
    > struct profil
    > {
    > struct point *pt;
    > struct profil *previous;
    > struct profil *next;
    > };
    >
    > int main(void)
    > {
    > int n;
    >
    > struct profil *p1;
    > struct profil *begin;
    >

    [. . .]
    >
    > /* put some information into the struct */
    >
    > p1->pt->x=1265.75;
    > p1->pt->y=150.73;
    >
    > p1->pt++; /* ugly, I know. Is there a better way to do this? */


    Yes, how about this:

    struct point *pt = p1->pt;
    pt[0].x = 1265.75;
    pt[0].y = 150.73;

    > p1->pt->x=550.55;
    > p1->pt->y=350.33;
    >
    > p1->pt--;


    pt[1].x = 550.55;
    pt[1].y = 350.33;

    >
    > /* do something with the structs */
    > /* instead of printing results, I print the structs out */
    >
    > printf("\nStrukt 1: %f\n", p1->pt->x);
    > printf("\nStrukt 1: %f\n", p1->pt->y);
    >
    > p1->pt++;
    >
    > printf("\nStrukt 2: %f\n", p1->pt->x);
    > printf("\nStrukt 2: %f\n", p1->pt->y);
    >
    > return 0;
    > }


    int i;
    for (i = 0; i < n; ++i)
    {
    printf("\nStrukt %d: %f\n", i + 1, pt.x);
    printf("\nStrukt %d: %f\n", i + 1, pt.y);
    }

    Regards,

    Russell Hanneken

    Remove the 'g' from my address to send me mail.
    Russell Hanneken, Nov 4, 2003
    #2
    1. Advertising

  3. Russell Hanneken wrote:
    > Roman Hartmann wrote:
    >>
    >> int main(void)
    >> {
    >> int n;
    >>
    >> struct profil *p1;
    >> struct profil *begin;
    >>

    [ . . . ]
    >
    > struct point *pt = p1->pt;
    > pt[0].x = 1265.75;
    > pt[0].y = 150.73;
    >
    > pt[1].x = 550.55;
    > pt[1].y = 350.33;
    >
    > int i;


    Oops; both i and pt need to be declared at the beginning of main. Unless
    you're writing code to conform to the new (1999) C standard (which you
    probably aren't), local variable declarations have to be at the beginning of
    a block, before any non-declaration code.

    Regards,

    Russell Hanneken

    Remove the 'g' from my address to send me mail.
    Russell Hanneken, Nov 4, 2003
    #3
  4. "Russell Hanneken" <> schrieb im Newsbeitrag
    news:a4Qpb.7519$...
    > Roman Hartmann wrote:
    > > I would like to know if there is a better way to access struct members
    > > (the points).
    > > Accessing struct members with p1->p2->x seems rather ugly and unsafe.
    > >

    > [. . .]
    > >
    > > /* struct with points, used by struct profil */
    > >
    > > struct point
    > > {
    > > double x;
    > > double y;
    > > };
    > >
    > > struct profil
    > > {
    > > struct point *pt;
    > > struct profil *previous;
    > > struct profil *next;
    > > };
    > >
    > > int main(void)
    > > {
    > > int n;
    > >
    > > struct profil *p1;
    > > struct profil *begin;
    > >

    > [. . .]
    > >
    > > /* put some information into the struct */
    > >
    > > p1->pt->x=1265.75;
    > > p1->pt->y=150.73;
    > >
    > > p1->pt++; /* ugly, I know. Is there a better way to do this? */

    >
    > Yes, how about this:
    >
    > struct point *pt = p1->pt;
    > pt[0].x = 1265.75;
    > pt[0].y = 150.73;


    Yes!
    It's much easier to deal with the points now that way.

    > > p1->pt->x=550.55;
    > > p1->pt->y=350.33;
    > >
    > > p1->pt--;

    >
    > pt[1].x = 550.55;
    > pt[1].y = 350.33;



    > >
    > > /* do something with the structs */
    > > /* instead of printing results, I print the structs out */
    > >
    > > printf("\nStrukt 1: %f\n", p1->pt->x);
    > > printf("\nStrukt 1: %f\n", p1->pt->y);
    > >
    > > p1->pt++;
    > >
    > > printf("\nStrukt 2: %f\n", p1->pt->x);
    > > printf("\nStrukt 2: %f\n", p1->pt->y);
    > >
    > > return 0;
    > > }

    >
    > int i;
    > for (i = 0; i < n; ++i)
    > {
    > printf("\nStrukt %d: %f\n", i + 1, pt.x);
    > printf("\nStrukt %d: %f\n", i + 1, pt.y);
    > }
    >
    > Regards,
    > Russell Hanneken


    thanks a lot!
    Roman
    Roman Hartmann, Nov 4, 2003
    #4
  5. On Tue, 04 Nov 2003 16:37:40 +0100, Roman Hartmann wrote:

    > #include <stdlib.h>
    > #include <stdio.h>
    >
    > /* struct with points, used by struct profil */
    >
    > struct point
    > {
    > double x;
    > double y;
    > };
    >
    > struct profil
    > {
    > struct point *pt;
    > struct profil *previous;
    > struct profil *next;
    > };
    >
    > int main(void)
    > {
    > int n;
    >
    > struct profil *p1;
    > struct profil *begin;
    >
    > n=2; /* only to allocate memory for this example */
    >
    > if((p1=(struct profil *) malloc(sizeof(struct profil)))==NULL)


    This line can be written more simply:

    if ((p1 = malloc(sizeof *p1)) == NULL)

    > {
    > printf("\nMemory allocation failed\n");
    > return 1;
    > }
    >
    > begin=p1;
    >
    > if((p1->pt=(struct point *) malloc(n*sizeof(struct point)))==NULL)


    This line too:

    if ((p1->pt = malloc(n * sizeof *p1->pt)) == NULL)

    > {
    > printf("\nMemory allocation failed\n");
    > return 1;
    > }
    >
    > /* put some information into the struct */
    >
    > p1->pt->x=1265.75;
    > p1->pt->y=150.73;
    >
    > p1->pt++; /* ugly, I know. Is there a better way to do this? */
    >
    > p1->pt->x=550.55;
    > p1->pt->y=350.33;
    >
    > p1->pt--;


    The only problem I see here is the unnecessary incrementing and
    decrementing of p1->pt. There is nothing wrong (or unsafe) with
    using an expression like p1->pt->x, but to avoid incrementing and
    decrementing p1->pt I would do the above like this:

    p1->pt[0].x = 1265.75;
    p1->pt[0].y = 150.73;
    p1->pt[1].x = 550.55;
    p1->pt[1].y = 350.33;

    -Sheldon
    Sheldon Simms, Nov 4, 2003
    #5
  6. Roman Hartmann

    Mark Gordon Guest

    On Tue, 4 Nov 2003 16:37:40 +0100
    "Roman Hartmann" <> wrote:

    > hello,
    > I do have a question regarding structs. I have a struct (profil)
    > which has a pointer to another struct (point). The struct profil
    > stores the coordinates of points.
    > The problem is that I don't know how many points
    > there will be in every struct in the end, so I have to allocate memory
    > dynamically for
    > them and can't use an array of fixed size, unfortunately.
    >
    > I would like to know if there is a better way to access struct members
    > (the points).
    > Accessing struct members with p1->p2->x seems rather ugly and unsafe.


    Yes, there are ways which IMHO are better and safer. If a is a pointer,
    a[0] is the object a points to, a[1] is the next object (if there is
    one) etc. I.e. although pointers and arrays are differed, you can use
    a pointer as if it was an array in THIS instance.

    > Below is a stripped down version of the program, just to get an idea
    > what I'm trying to do. I'm aware that this is not a pure ANSI C
    > definition question,


    It is a question about how to do something in ANSI C (or any ISO C or
    K&R C) so you have come to the right place.

    > but I couldn't find any help to this special
    > problem neither in K&R nor in the FAQ. So I apreciate every hint.


    It's there somewhere, but you've failed to find it so I'll tell you. We
    don't mind people failing to find what they are looking for, or failing
    to understand it, it's when people don't try it's a problem.

    > #include <stdlib.h>
    > #include <stdio.h>
    >
    > /* struct with points, used by struct profil */
    >
    > struct point
    > {
    > double x;
    > double y;
    > };
    >
    > struct profil
    > {
    > struct point *pt;
    > struct profil *previous;
    > struct profil *next;
    > };
    >
    > int main(void)
    > {
    > int n;
    >
    > struct profil *p1;
    > struct profil *begin;


    You don't use begin (apart from assigning to it) so delete it.

    > n=2; /* only to allocate memory for this example */
    >
    > if((p1=(struct profil *) malloc(sizeof(struct profil)))==NULL)


    if((p1=malloc(sizeof *p1))==NULL)
    is far safer.

    If you had failed to include stdlib.h casting the return value of malloc
    prevents the compiler from giving you a warning it is otherwise REQUIRED
    to give. It may *still* give a warning, depending on how good the
    compiler is. However, why replace a requirement with a hope?

    Using sizeof *p1 meens that if you change the type of p1 the malloc will
    still allocate the correct amount of space.

    > {
    > printf("\nMemory allocation failed\n");
    > return 1;
    > }
    >
    > begin=p1;
    >
    > if((p1->pt=(struct point *) malloc(n*sizeof(struct
    > point)))==NULL){


    if((p1->pt=malloc(n*sizeof *p1->pt))==NULL)

    See above.

    > printf("\nMemory allocation failed\n");
    > return 1;
    > }


    <snip>

    I've replaced the rest of your code with the following...

    /* put some information into the struct */

    p1->pt[0].x=1265.75;
    p1->pt[0].y=150.73;

    p1->pt[1].x=550.55;
    p1->pt[1].y=350.33;

    /* do something with the structs */
    /* instead of printing results, I print the structs out */

    printf("\nStrukt 1: %f\n", p1->pt[0].x);
    printf("\nStrukt 1: %f\n", p1->pt[0].y);

    printf("\nStrukt 2: %f\n", p1->pt[1].x);
    printf("\nStrukt 2: %f\n", p1->pt[1].y);

    free(p1->pt);
    free(p1);

    return 0;
    }

    Note that I've also freed the storage at the end. After all, we don't
    want any memory leaks when you put this in a function ;-)
    --
    Mark Gordon
    Paid to be a Geek & a Senior Software Developer
    Although my email address says spamtrap, it is real and I read it.
    Mark Gordon, Nov 4, 2003
    #6
  7. Roman Hartmann

    Al Bowers Guest

    Roman Hartmann wrote:
    > hello,
    > I do have a question regarding structs. I have a struct (profil) which
    > has a pointer to another struct (point). The struct profil stores the
    > coordinates of points.
    > The problem is that I don't know how many points
    > there will be in every struct in the end, so I have to allocate memory
    > dynamically for
    > them and can't use an array of fixed size, unfortunately.
    >
    > I would like to know if there is a better way to access struct members (the
    > points).
    > Accessing struct members with p1->p2->x seems rather ugly and unsafe.
    >
    > Below is a stripped down version of the program, just to get an idea what
    > I'm trying to do. I'm aware that this is not a pure ANSI C definition
    > question, but I couldn't find any help to this special problem neither in
    > K&R nor in the FAQ. So I apreciate every hint.
    >
    > Best Regards
    > Roman
    >
    > #include <stdlib.h>
    > #include <stdio.h>
    >
    > /* struct with points, used by struct profil */
    >
    > struct point
    > {
    > double x;
    > double y;
    > };
    >
    > struct profil
    > {
    > struct point *pt;
    > struct profil *previous;
    > struct profil *next;
    > };


    I would add another member to struct profil to keep a count
    on the number of points you allocated.

    To facilitate the code writing, you can write functions that will
    manipulate the data structure.

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

    struct point
    {
    double x;
    double y;
    };

    struct profil
    {
    struct point *pt;
    size_t pt_count;
    struct profil *previous;
    struct profil *next;
    };

    struct profil *CreateProfil(size_t pt_number);
    void AssignPoints(struct point *p, double x, double y);
    void PrintProfilPoints(struct profil *p);
    void InsertLink(struct profil **root, struct profil *src);
    void PrintLinkPoints(struct profil *root);
    void FreeLink(struct profil **root);


    int main(void)
    {
    struct profil *link = NULL;
    struct profil *p1 = CreateProfil(3);
    if(p1 != NULL)
    {
    AssignPoints(&p1->pt[0],2.33,4.44);
    AssignPoints(&p1->pt[1], 4.67, 6.89);
    AssignPoints(&p1->pt[2], 7.77,8.98);
    InsertLink(&link,p1);
    }
    if((p1 = CreateProfil(2)) != NULL)
    {
    AssignPoints(&p1->pt[0], 1.11,2.22);
    AssignPoints(&p1->pt[1], 3.33,4.44);
    InsertLink(&link,p1);
    }
    PrintLinkPoints(link);
    FreeLink(&link);
    return 0;
    }

    struct profil *CreateProfil(size_t pt_number)
    {
    struct profil *p;

    if((p = malloc(sizeof *p)) == NULL) return NULL;
    p->pt_count = pt_number;
    p->previous = p->next = NULL;
    if(pt_number > 0)
    {
    if((p->pt = malloc(pt_number*(sizeof *p->pt))) == NULL)
    {
    free(p);
    return NULL;
    }
    }
    else p->pt = NULL;
    return p;
    }

    void AssignPoints(struct point *p, double x, double y)
    {
    p->x = x;
    p->y = y;
    return;
    }

    void PrintProfilPoints(struct profil *p)
    {
    size_t i;

    for(i = 0; i < p->pt_count; i++)
    printf("point: x = %.2f\t\ty = %.2f\n",p->pt.x,
    p->pt.y);
    return;
    }


    void InsertLink(struct profil **root, struct profil *src)
    {
    if(*root != NULL)
    {
    src->next = *root;
    (*root)->previous = src;
    }
    *root = src;
    return;
    }

    void PrintLinkPoints(struct profil *root)
    {
    size_t i = 1;
    if(root)
    {
    for( ; root->next; root = root->next);
    for( ; root; root = root->previous)
    {
    printf("Link: %u\n",i++);
    PrintProfilPoints(root);
    putchar('\n');
    }
    }
    return;
    }

    void FreeLink(struct profil **root)
    {
    struct profil *tmp;

    for( ; *root; *root = tmp)
    {
    tmp = (*root)->next;
    free((*root)->pt);
    free(*root);
    }
    }





    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
    Al Bowers, Nov 4, 2003
    #7
  8. Roman Hartmann

    John Bode Guest

    "Roman Hartmann" <> wrote in message news:<3fa7c85f$>...
    > hello,
    > I do have a question regarding structs. I have a struct (profil) which
    > has a pointer to another struct (point). The struct profil stores the
    > coordinates of points.
    > The problem is that I don't know how many points
    > there will be in every struct in the end, so I have to allocate memory
    > dynamically for
    > them and can't use an array of fixed size, unfortunately.
    >
    > I would like to know if there is a better way to access struct members (the
    > points).
    > Accessing struct members with p1->p2->x seems rather ugly and unsafe.


    You could write functions to hide this access:

    void setPt (struct pt *p, double x, double y)
    {
    p->x = x;
    p->y = y;
    }

    void setProfilePt (struct profile *p, size_t idx, double x, double
    y)
    {
    setPt (&(p->pt[idx]), x, y);
    }

    I'll show their use below.

    >
    > Below is a stripped down version of the program, just to get an idea what
    > I'm trying to do. I'm aware that this is not a pure ANSI C definition
    > question, but I couldn't find any help to this special problem neither in
    > K&R nor in the FAQ. So I apreciate every hint.
    >
    > Best Regards
    > Roman
    >
    > #include <stdlib.h>
    > #include <stdio.h>
    >
    > /* struct with points, used by struct profil */
    >
    > struct point
    > {
    > double x;
    > double y;
    > };
    >
    > struct profil
    > {
    > struct point *pt;
    > struct profil *previous;
    > struct profil *next;
    > };
    >
    > int main(void)
    > {
    > int n;
    >
    > struct profil *p1;
    > struct profil *begin;
    >
    > n=2; /* only to allocate memory for this example */
    >
    > if((p1=(struct profil *) malloc(sizeof(struct profil)))==NULL)


    Don't cast the return value of malloc(). You don't need to (as of
    C89, anyway), and it may supress a compiler warning if you ever forget
    to #include stdlib.h.

    This is a bit cleaner, and works just as well:

    if ((p1 = malloc (sizeof *p1)) != NULL)

    > {
    > printf("\nMemory allocation failed\n");
    > return 1;
    > }
    >
    > begin=p1;
    >
    > if((p1->pt=(struct point *) malloc(n*sizeof(struct point)))==NULL)


    Same point as above.

    if ((p1->pt = malloc (n * sizeof *(p1->pt))) == NULL)
    > {
    > printf("\nMemory allocation failed\n");
    > return 1;
    > }
    >
    > /* put some information into the struct */
    >
    > p1->pt->x=1265.75;
    > p1->pt->y=150.73;
    >
    > p1->pt++; /* ugly, I know. Is there a better way to do this? */


    Use array subscript notation instead:

    p1->pt[0].x = 1265.75;
    p1->pt[0].y = 150.73;

    p1->pt[1].x = 550.55;
    p1->pt[1].y = 350.33;

    Actually, this is where you'd use the assignment functions I defined
    above:

    setProfilePt (p, 0, 1265.75, 150.73);
    setProfilePt (p, 1, 550.55, 350.33);

    >
    > p1->pt->x=550.55;
    > p1->pt->y=350.33;
    >
    > p1->pt--;
    >
    > /* do something with the structs */
    > /* instead of printing results, I print the structs out */
    >
    > printf("\nStrukt 1: %f\n", p1->pt->x);
    > printf("\nStrukt 1: %f\n", p1->pt->y);
    >
    > p1->pt++;
    >
    > printf("\nStrukt 2: %f\n", p1->pt->x);
    > printf("\nStrukt 2: %f\n", p1->pt->y);


    Same thing: use array subscript notation instead of incrementing your
    pointer.

    printf ("\nStrukt 1: {%f,%f}\n", p1->pt[0].x, p1->pt[0].y);
    printf ("\nStrukt 2: {%f,%f}\n", p1->pt[1].x, p1->pt[1].y);

    This would also be a good excuse for creating accessor functions:

    double ptX (struct pt p) { return p.x; }
    double ptY (struct pt p) { return p.y; }

    void getProfilePt (struct profile *p, size_t idx, double *x,
    double *y)
    {
    *x = ptX (p->pt[idx]);
    *y = ptY (p->pt[idx]);
    }
    >
    > return 0;
    > }
    John Bode, Nov 4, 2003
    #8
  9. "Sheldon Simms" <> schrieb im Newsbeitrag
    news:p...
    > On Tue, 04 Nov 2003 16:37:40 +0100, Roman Hartmann wrote:


    [ ...]

    > > if((p1=(struct profil *) malloc(sizeof(struct profil)))==NULL)

    >
    > This line can be written more simply:
    >
    > if ((p1 = malloc(sizeof *p1)) == NULL)


    I never dealt with malloc before, so I really appreciate this hint.

    > > {
    > > printf("\nMemory allocation failed\n");
    > > return 1;
    > > }
    > >
    > > begin=p1;
    > >
    > > if((p1->pt=(struct point *) malloc(n*sizeof(struct point)))==NULL)

    >
    > This line too:
    >
    > if ((p1->pt = malloc(n * sizeof *p1->pt)) == NULL)
    >
    > > {
    > > printf("\nMemory allocation failed\n");
    > > return 1;
    > > }


    [ ... ]

    > > p1->pt->x=550.55;
    > > p1->pt->y=350.33;
    > >
    > > p1->pt--;

    >
    > The only problem I see here is the unnecessary incrementing and
    > decrementing of p1->pt. There is nothing wrong (or unsafe) with
    > using an expression like p1->pt->x, but to avoid incrementing and
    > decrementing p1->pt I would do the above like this:
    >
    > p1->pt[0].x = 1265.75;
    > p1->pt[0].y = 150.73;
    > p1->pt[1].x = 550.55;
    > p1->pt[1].y = 350.33;


    That is simpler and more obvious than incrementing a pointer.

    thanks a lot
    Roman

    > -Sheldon
    Roman Hartmann, Nov 5, 2003
    #9
  10. "Mark Gordon" <> schrieb im Newsbeitrag
    news:...
    > On Tue, 4 Nov 2003 16:37:40 +0100
    > "Roman Hartmann" <> wrote:
    >
    > > hello,
    > > I do have a question regarding structs. I have a struct (profil)
    > > which has a pointer to another struct (point). The struct profil
    > > stores the coordinates of points.
    > > The problem is that I don't know how many points
    > > there will be in every struct in the end, so I have to allocate memory
    > > dynamically for
    > > them and can't use an array of fixed size, unfortunately.
    > >
    > > I would like to know if there is a better way to access struct members
    > > (the points).
    > > Accessing struct members with p1->p2->x seems rather ugly and unsafe.

    >
    > Yes, there are ways which IMHO are better and safer. If a is a pointer,
    > a[0] is the object a points to, a[1] is the next object (if there is
    > one) etc. I.e. although pointers and arrays are differed, you can use
    > a pointer as if it was an array in THIS instance.


    Well, I couldn't see the most obvious solution.

    > > Below is a stripped down version of the program, just to get an idea
    > > what I'm trying to do. I'm aware that this is not a pure ANSI C
    > > definition question,

    >
    > It is a question about how to do something in ANSI C (or any ISO C or
    > K&R C) so you have come to the right place.
    >
    > > but I couldn't find any help to this special
    > > problem neither in K&R nor in the FAQ. So I apreciate every hint.

    >
    > It's there somewhere, but you've failed to find it so I'll tell you. We
    > don't mind people failing to find what they are looking for, or failing
    > to understand it, it's when people don't try it's a problem.
    >
    > > #include <stdlib.h>
    > > #include <stdio.h>
    > >
    > > /* struct with points, used by struct profil */
    > >
    > > struct point
    > > {
    > > double x;
    > > double y;
    > > };
    > >
    > > struct profil
    > > {
    > > struct point *pt;
    > > struct profil *previous;
    > > struct profil *next;
    > > };
    > >
    > > int main(void)
    > > {
    > > int n;
    > >
    > > struct profil *p1;
    > > struct profil *begin;

    >
    > You don't use begin (apart from assigning to it) so delete it.
    >
    > > n=2; /* only to allocate memory for this example */
    > >
    > > if((p1=(struct profil *) malloc(sizeof(struct profil)))==NULL)

    >
    > if((p1=malloc(sizeof *p1))==NULL)
    > is far safer.


    Thanks for this info.

    > If you had failed to include stdlib.h casting the return value of malloc
    > prevents the compiler from giving you a warning it is otherwise REQUIRED
    > to give. It may *still* give a warning, depending on how good the
    > compiler is. However, why replace a requirement with a hope?
    >
    > Using sizeof *p1 meens that if you change the type of p1 the malloc will
    > still allocate the correct amount of space.


    Well, pointers and dynamic memory allocation seem to be the hard part for
    newbies on C.

    > > {
    > > printf("\nMemory allocation failed\n");
    > > return 1;
    > > }
    > >
    > > begin=p1;
    > >
    > > if((p1->pt=(struct point *) malloc(n*sizeof(struct
    > > point)))==NULL){

    >
    > if((p1->pt=malloc(n*sizeof *p1->pt))==NULL)
    >
    > See above.
    >
    > > printf("\nMemory allocation failed\n");
    > > return 1;
    > > }

    >
    > <snip>
    >
    > I've replaced the rest of your code with the following...
    >
    > /* put some information into the struct */
    >
    > p1->pt[0].x=1265.75;
    > p1->pt[0].y=150.73;
    >
    > p1->pt[1].x=550.55;
    > p1->pt[1].y=350.33;


    I don't know why I didn't have figured out, myself. It's so obvious.

    > /* do something with the structs */
    > /* instead of printing results, I print the structs out */
    >
    > printf("\nStrukt 1: %f\n", p1->pt[0].x);
    > printf("\nStrukt 1: %f\n", p1->pt[0].y);
    >
    > printf("\nStrukt 2: %f\n", p1->pt[1].x);
    > printf("\nStrukt 2: %f\n", p1->pt[1].y);
    >
    > free(p1->pt);
    > free(p1);
    >
    > return 0;
    > }
    >
    > Note that I've also freed the storage at the end. After all, we don't
    > want any memory leaks when you put this in a function ;-)


    Thanks a lot. I appreciate your help.

    Roman

    > Mark Gordon
    > Paid to be a Geek & a Senior Software Developer
    > Although my email address says spamtrap, it is real and I read it.
    Roman Hartmann, Nov 5, 2003
    #10
  11. "Al Bowers" <> schrieb im Newsbeitrag
    news:bo8nbf$1abjn9$-berlin.de...
    >
    >
    > Roman Hartmann wrote:
    > > hello,
    > > I do have a question regarding structs. I have a struct (profil) which
    > > has a pointer to another struct (point). The struct profil stores the
    > > coordinates of points.
    > > The problem is that I don't know how many points
    > > there will be in every struct in the end, so I have to allocate memory
    > > dynamically for
    > > them and can't use an array of fixed size, unfortunately.
    > >
    > > I would like to know if there is a better way to access struct members

    (the
    > > points).
    > > Accessing struct members with p1->p2->x seems rather ugly and unsafe.
    > >
    > > Below is a stripped down version of the program, just to get an idea

    what
    > > I'm trying to do. I'm aware that this is not a pure ANSI C definition
    > > question, but I couldn't find any help to this special problem neither

    in
    > > K&R nor in the FAQ. So I apreciate every hint.
    > >
    > > Best Regards
    > > Roman
    > >
    > > #include <stdlib.h>
    > > #include <stdio.h>
    > >
    > > /* struct with points, used by struct profil */
    > >
    > > struct point
    > > {
    > > double x;
    > > double y;
    > > };
    > >
    > > struct profil
    > > {
    > > struct point *pt;
    > > struct profil *previous;
    > > struct profil *next;
    > > };

    >
    > I would add another member to struct profil to keep a count
    > on the number of points you allocated.
    >
    > To facilitate the code writing, you can write functions that will
    > manipulate the data structure.


    Good idea. I will do that if I know better what I'm actually doing;-)

    > #include <stdlib.h>
    > #include <stdio.h>
    >
    > struct point
    > {
    > double x;
    > double y;
    > };
    >
    > struct profil
    > {
    > struct point *pt;
    > size_t pt_count;
    > struct profil *previous;
    > struct profil *next;
    > };
    >
    > struct profil *CreateProfil(size_t pt_number);
    > void AssignPoints(struct point *p, double x, double y);
    > void PrintProfilPoints(struct profil *p);
    > void InsertLink(struct profil **root, struct profil *src);
    > void PrintLinkPoints(struct profil *root);
    > void FreeLink(struct profil **root);
    >
    >
    > int main(void)
    > {
    > struct profil *link = NULL;
    > struct profil *p1 = CreateProfil(3);
    > if(p1 != NULL)
    > {
    > AssignPoints(&p1->pt[0],2.33,4.44);
    > AssignPoints(&p1->pt[1], 4.67, 6.89);
    > AssignPoints(&p1->pt[2], 7.77,8.98);
    > InsertLink(&link,p1);
    > }
    > if((p1 = CreateProfil(2)) != NULL)
    > {
    > AssignPoints(&p1->pt[0], 1.11,2.22);
    > AssignPoints(&p1->pt[1], 3.33,4.44);
    > InsertLink(&link,p1);
    > }
    > PrintLinkPoints(link);
    > FreeLink(&link);
    > return 0;
    > }
    >
    > struct profil *CreateProfil(size_t pt_number)
    > {
    > struct profil *p;
    >
    > if((p = malloc(sizeof *p)) == NULL) return NULL;
    > p->pt_count = pt_number;
    > p->previous = p->next = NULL;
    > if(pt_number > 0)
    > {
    > if((p->pt = malloc(pt_number*(sizeof *p->pt))) == NULL)
    > {
    > free(p);
    > return NULL;
    > }
    > }
    > else p->pt = NULL;
    > return p;
    > }
    >
    > void AssignPoints(struct point *p, double x, double y)
    > {
    > p->x = x;
    > p->y = y;
    > return;
    > }
    >
    > void PrintProfilPoints(struct profil *p)
    > {
    > size_t i;
    >
    > for(i = 0; i < p->pt_count; i++)
    > printf("point: x = %.2f\t\ty = %.2f\n",p->pt.x,
    > p->pt.y);
    > return;
    > }
    >
    >
    > void InsertLink(struct profil **root, struct profil *src)
    > {
    > if(*root != NULL)
    > {
    > src->next = *root;
    > (*root)->previous = src;
    > }
    > *root = src;
    > return;
    > }
    >
    > void PrintLinkPoints(struct profil *root)
    > {
    > size_t i = 1;
    > if(root)
    > {
    > for( ; root->next; root = root->next);
    > for( ; root; root = root->previous)
    > {
    > printf("Link: %u\n",i++);
    > PrintProfilPoints(root);
    > putchar('\n');
    > }
    > }
    > return;
    > }
    >
    > void FreeLink(struct profil **root)
    > {
    > struct profil *tmp;
    >
    > for( ; *root; *root = tmp)
    > {
    > tmp = (*root)->next;
    > free((*root)->pt);
    > free(*root);
    > }
    > }


    Thanks a lot for this. I learned a lot from that example and will probably
    use some parts (or at least the concept) of this.
    Thanks again!

    Roman

    > --
    > Al Bowers
    > Tampa, Fl USA
    > mailto: (remove the x to send email)
    > http://www.geocities.com/abowers822/
    >
    Roman Hartmann, Nov 5, 2003
    #11
  12. "John Bode" <> schrieb im Newsbeitrag
    news:...
    > "Roman Hartmann" <> wrote in message

    news:<3fa7c85f$>...
    > > hello,
    > > I do have a question regarding structs. I have a struct (profil) which
    > > has a pointer to another struct (point). The struct profil stores the
    > > coordinates of points.
    > > The problem is that I don't know how many points
    > > there will be in every struct in the end, so I have to allocate memory
    > > dynamically for
    > > them and can't use an array of fixed size, unfortunately.
    > >
    > > I would like to know if there is a better way to access struct members

    (the
    > > points).
    > > Accessing struct members with p1->p2->x seems rather ugly and unsafe.

    >
    > You could write functions to hide this access:
    > void setPt (struct pt *p, double x, double y)
    > {
    > p->x = x;
    > p->y = y;
    > }
    >
    > void setProfilePt (struct profile *p, size_t idx, double x, double
    > y)
    > {
    > setPt (&(p->pt[idx]), x, y);
    > }
    >
    > I'll show their use below.
    >
    > >
    > > Below is a stripped down version of the program, just to get an idea

    what
    > > I'm trying to do. I'm aware that this is not a pure ANSI C definition
    > > question, but I couldn't find any help to this special problem neither

    in
    > > K&R nor in the FAQ. So I apreciate every hint.
    > >
    > > Best Regards
    > > Roman
    > >
    > > #include <stdlib.h>
    > > #include <stdio.h>
    > >
    > > /* struct with points, used by struct profil */
    > >
    > > struct point
    > > {
    > > double x;
    > > double y;
    > > };
    > >
    > > struct profil
    > > {
    > > struct point *pt;
    > > struct profil *previous;
    > > struct profil *next;
    > > };
    > >
    > > int main(void)
    > > {
    > > int n;
    > >
    > > struct profil *p1;
    > > struct profil *begin;
    > >
    > > n=2; /* only to allocate memory for this example */
    > >
    > > if((p1=(struct profil *) malloc(sizeof(struct profil)))==NULL)

    >
    > Don't cast the return value of malloc(). You don't need to (as of
    > C89, anyway), and it may supress a compiler warning if you ever forget
    > to #include stdlib.h.
    >
    > This is a bit cleaner, and works just as well:
    >
    > if ((p1 = malloc (sizeof *p1)) != NULL)


    It gives me some confident that all the people are doing the memory
    allocation the same way.

    > > {
    > > printf("\nMemory allocation failed\n");
    > > return 1;
    > > }
    > >
    > > begin=p1;
    > >
    > > if((p1->pt=(struct point *) malloc(n*sizeof(struct point)))==NULL)

    >
    > Same point as above.
    >
    > if ((p1->pt = malloc (n * sizeof *(p1->pt))) == NULL)
    > > {
    > > printf("\nMemory allocation failed\n");
    > > return 1;
    > > }
    > >
    > > /* put some information into the struct */
    > >
    > > p1->pt->x=1265.75;
    > > p1->pt->y=150.73;
    > >
    > > p1->pt++; /* ugly, I know. Is there a better way to do this? */

    >
    > Use array subscript notation instead:
    >
    > p1->pt[0].x = 1265.75;
    > p1->pt[0].y = 150.73;
    >
    > p1->pt[1].x = 550.55;
    > p1->pt[1].y = 350.33;
    >
    > Actually, this is where you'd use the assignment functions I defined
    > above:
    >
    > setProfilePt (p, 0, 1265.75, 150.73);
    > setProfilePt (p, 1, 550.55, 350.33);
    >
    > >
    > > p1->pt->x=550.55;
    > > p1->pt->y=350.33;
    > >
    > > p1->pt--;
    > >
    > > /* do something with the structs */
    > > /* instead of printing results, I print the structs out */
    > >
    > > printf("\nStrukt 1: %f\n", p1->pt->x);
    > > printf("\nStrukt 1: %f\n", p1->pt->y);
    > >
    > > p1->pt++;
    > >
    > > printf("\nStrukt 2: %f\n", p1->pt->x);
    > > printf("\nStrukt 2: %f\n", p1->pt->y);

    >
    > Same thing: use array subscript notation instead of incrementing your
    > pointer.
    >
    > printf ("\nStrukt 1: {%f,%f}\n", p1->pt[0].x, p1->pt[0].y);
    > printf ("\nStrukt 2: {%f,%f}\n", p1->pt[1].x, p1->pt[1].y);
    >
    > This would also be a good excuse for creating accessor functions:
    >
    > double ptX (struct pt p) { return p.x; }
    > double ptY (struct pt p) { return p.y; }
    >
    > void getProfilePt (struct profile *p, size_t idx, double *x,
    > double *y)
    > {
    > *x = ptX (p->pt[idx]);
    > *y = ptY (p->pt[idx]);
    > }
    > >
    > > return 0;
    > > }


    thanks for your help!
    Roman
    Roman Hartmann, Nov 5, 2003
    #12
    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. Patricia  Van Hise

    structs with fields that are structs

    Patricia Van Hise, Apr 5, 2004, in forum: C Programming
    Replies:
    5
    Views:
    635
    Al Bowers
    Apr 5, 2004
  2. s.subbarayan

    Dynamic memory allocation and memory leak...

    s.subbarayan, Mar 18, 2005, in forum: C Programming
    Replies:
    10
    Views:
    698
    Eric Sosman
    Mar 22, 2005
  3. Ken
    Replies:
    24
    Views:
    3,862
    Ben Bacarisse
    Nov 30, 2006
  4. chris
    Replies:
    6
    Views:
    988
    chris
    Oct 28, 2005
  5. Durango

    problem with memory allocation and structs

    Durango, Dec 4, 2011, in forum: C Programming
    Replies:
    5
    Views:
    335
    Durango
    Dec 9, 2011
Loading...

Share This Page