2D array of structures

Discussion in 'C Programming' started by svata, Nov 7, 2006.

  1. svata

    svata Guest

    Hello,

    I wonder how to resize such array of structures using realloc()?

    #include <stdio.h>
    #include <stdlib.h>
    #define FIRST 7

    typedef struct {
    char *name;
    int i;
    int j;
    } STRUCTURE;

    STRUCTURE **p_structure;

    int main() {

    p_structure = (STRUCTURE **) malloc(FIRST * sizeof(STRUCTURE));
    if ( p_structure == NULL ) {
    printf("Failed to allocate memory, exiting...");
    return 1;
    }
    }

    Thank you in advance

    Svata
     
    svata, Nov 7, 2006
    #1
    1. Advertising

  2. svata <> wrote:
    > I wonder how to resize such array of structures using realloc()?


    > #include <stdio.h>
    > #include <stdlib.h>
    > #define FIRST 7


    > typedef struct {
    > char *name;
    > int i;
    > int j;
    > } STRUCTURE;


    > STRUCTURE **p_structure;


    > int main() {


    Make that

    int main( void )

    since your main() takes no arguments.

    > p_structure = (STRUCTURE **) malloc(FIRST * sizeof(STRUCTURE));


    Don't cast the return value of malloc(), it only hides your mistake
    should you have forgotten to include <stdlib.h>. But, more important,
    you allocate here memory for 7 (FIRST) such structures. malloc() returns
    a pointer to the start of this memory, which is of type 'STRUCTURE *'
    (malloc() actually returns a void pointer but "STRUCTURE *' is the
    correct type of a pointer to that memory). But you assign it instead
    to a pointer that has type 'STRUCTURE **'. That, combined with your
    use of the words "2D array" in the subjct line, leads to the suspicion
    that you actually don't want to allocate memory for something that has
    similar properties as an array of stuctures, but something more compli-
    cated and similar to a 2D array of such structures. And that's what you
    definitely won't get with that allocation, whatever the type of the
    pointer you assign the return value of malloc() to. So, instead of
    starting to guess what you might have intended I think it's better to
    ask you to specify a bit more clearly what you intend to do here: do
    you just want memory for a simple set of structures or do you want
    something like a 2D array of such structures. In the first case you
    could "repair" your program by simply defining 'p_structure' as

    STTRUCTURE *p_structure;

    Perhaps you thenn also might want to replace the line for the allo-
    cation by

    p_structure = malloc(FIRST * sizeof *p_structure);

    because that way you don't have to change that line anymore if you
    should decide to change the type of 'p_structure' sometime later.

    You also write something about realloc() but I can't see any
    use or mentioning of realloc() in the code you posted. But, of
    course, you can use realloc() to resize the amount of memory
    you obtained from malloc() - that's what realloc() was invented
    for.

    > if ( p_structure == NULL ) {
    > printf("Failed to allocate memory, exiting...");
    > return 1;
    > }


    It's good to see that you check that what malloc() returned!

    > }


    Since main() returns an int, here's a missing line with a return
    value...
    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
     
    Jens Thoms Toerring, Nov 7, 2006
    #2
    1. Advertising

  3. svata

    Flash Gordon Guest

    Jens Thoms Toerring wrote:
    > svata <> wrote:


    <snip>

    >> p_structure = (STRUCTURE **) malloc(FIRST * sizeof(STRUCTURE));


    <snip>

    > correct type of a pointer to that memory). But you assign it instead
    > to a pointer that has type 'STRUCTURE **'. That, combined with your
    > use of the words "2D array" in the subjct line, leads to the suspicion
    > that you actually don't want to allocate memory for something that has
    > similar properties as an array of stuctures, but something more compli-
    > cated and similar to a 2D array of such structures. And that's what you


    <snip>

    I agree with what you've said, but the OP should also read section 6 of
    the comp.lang.c FAQ before posting back here. Section 6 includes ways of
    dynamically allocating space for things that work like 2D arrays. The
    FAQ can be found at http://c-faq.com/
    --
    Flash Gordon
     
    Flash Gordon, Nov 7, 2006
    #3
  4. svata:

    > STRUCTURE **p_structure;



    This is a pointer to a pointer to a STRUCTURE.

    (I'm against the use of ALL CAPS for anything other than macros)


    > int main() {
    >
    > p_structure = (STRUCTURE **) malloc(FIRST * sizeof(STRUCTURE));



    This doesn't make sense.

    You have a pointer to a pointer to a STRUCTURE. This would suggest to me
    that you're going to store either of the following in it:

    (1) The address of a pointer to a STRUCTURE.
    (2) The address of the first element of an array, whereby each element
    is a pointer to a STRUCTURE.

    If it were either of the two above, the "malloc" invocation should look
    something like:

    p_structure = malloc( sizeof(STRUCTURE*) );
    or:
    p_structure = malloc( 12 * sizeof(STRUCTURE*) );

    Note that I use the size of a "STRUCTURE*" rather than the size of a
    "STRUCTURE".

    Of course, it's better to write the two of them as:

    p_structure = malloc(sizeof*p);

    p_structure = malloc(12 * sizeof*p);

    --

    Frederick Gotham
     
    Frederick Gotham, Nov 7, 2006
    #4
  5. svata

    CBFalconer Guest

    svata wrote:
    >
    > I wonder how to resize such array of structures using realloc()?
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > #define FIRST 7
    >
    > typedef struct {
    > char *name;
    > int i;
    > int j;
    > } STRUCTURE;
    >
    > STRUCTURE **p_structure;


    Too many *s here.

    >
    > int main() {


    You
    >
    > p_structure = (STRUCTURE **) malloc(FIRST * sizeof(STRUCTURE));


    and here. Also _never_ cast the return from malloc (it only hides
    errors without fixing them). You want:

    p_structure = malloc(FIRST * sizeof *p_structure);

    > if ( p_structure == NULL ) {
    > printf("Failed to allocate memory, exiting...");
    > return 1;
    > }
    > }


    You can then change the size to, say, SECOND with:

    STRUCTURE *tmp; /* in a suitable location, not here */

    if (tmp = realloc(p_structure, SECOND) p_structure = tmp;
    else {
    /* handle lack of memory */
    }

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>
     
    CBFalconer, Nov 7, 2006
    #5
  6. svata

    svata Guest

    Hello Frederick,

    I know it doesn't make sense. I was wrong in my assumption.
    I should use p_structure = (STRUCTURE **) malloc(FIRST *
    sizeof(STRUCTURE*));

    but anyway... should rather use array of structures.


    typedef structure {
    code goes here...
    } _structure;

    _structure *p_structure;
    // and then malloc()

    p_structure = malloc( INT * sizeof(_structure));

    if am I right?

    svata

    Frederick Gotham wrote:

    > > STRUCTURE **p_structure;

    >
    >
    > This is a pointer to a pointer to a STRUCTURE.
    >
    > (I'm against the use of ALL CAPS for anything other than macros)
    >
    >
    > > int main() {
    > >
    > > p_structure = (STRUCTURE **) malloc(FIRST * sizeof(STRUCTURE));

    >
    >
    > This doesn't make sense.
    >


    > --
    >
    > Frederick Gotham
     
    svata, Nov 9, 2006
    #6
  7. svata

    Chris Dollin Guest

    svata wrote:

    > Hello Frederick,
    >
    > I know it doesn't make sense. I was wrong in my assumption.
    > I should use p_structure = (STRUCTURE **) malloc(FIRST *
    > sizeof(STRUCTURE*));


    No, you shouldn't: it's wiser to drop the unnecessary cast an
    to ensure that the thing you sizeof is appropriate for the
    pointer:

    pStructure = malloc( FIRST * sizeof (*pStructure) );

    which will (try to) mallocate space for FIRST (horrid name)
    lumps of space adequate for the kinds of thing that
    pStructure points to.

    > but anyway... should rather use array of structures.


    Yes, get rid of the unnecessary layer of indirection.

    > typedef structure {
    > code goes here...
    > } _structure;


    There are two things wrong with this. One is that it's
    syntax is broken, since you spelt "struct" "structure".
    The other is that so many names beginning with _ are
    reserved to the implementation it's unwise for you to
    define /any/ name that does. So don't.

    If you /must/ use a typedef for a structure -- you don't
    need to, and some wise people argue that you shouldn't
    (although others argue that those arguments aren't
    convincing) -- you should also give it a /sensible/
    name. "structure" isn't.

    typedef struct yourStructTagHere
    {
    int x;
    int y;
    } Point;

    --
    Chris ".enable proofreading" Dollin
    The "good old days" used to be much better.
     
    Chris Dollin, Nov 9, 2006
    #7
  8. svata

    svata Guest

    Chris Dollin wrote:

    I learn by doing. So I will see what results I get.

    > pStructure = malloc( FIRST * sizeof (*pStructure) );
    >
    > which will (try to) mallocate space for FIRST (horrid name)
    > lumps of space adequate for the kinds of thing that
    > pStructure points to.
    >
    > > but anyway... should rather use array of structures.

    >
    > Yes, get rid of the unnecessary layer of indirection.
    >
    > > typedef structure {
    > > code goes here...
    > > } _structure;

    >
    > There are two things wrong with this. One is that it's
    > syntax is broken, since you spelt "struct" "structure".
    > The other is that so many names beginning with _ are
    > reserved to the implementation it's unwise for you to
    > define /any/ name that does. So don't.
    >
    > If you /must/ use a typedef for a structure -- you don't
    > need to, and some wise people argue that you shouldn't
    > (although others argue that those arguments aren't
    > convincing) -- you should also give it a /sensible/
    > name. "structure" isn't.
    >
    > typedef struct yourStructTagHere
    > {
    > int x;
    > int y;
    > } Point;
    >
    > --
    > Chris ".enable proofreading" Dollin
    > The "good old days" used to be much better.
     
    svata, Nov 9, 2006
    #8
  9. svata

    svata Guest

    I always use google to search an answer, but often results are not
    relevant.


    svata
    >
    > I agree with what you've said, but the OP should also read section 6 of
    > the comp.lang.c FAQ before posting back here. Section 6 includes ways of
    > dynamically allocating space for things that work like 2D arrays. The
    > FAQ can be found at http://c-faq.com/
    > --
    > Flash Gordon
     
    svata, Nov 9, 2006
    #9
  10. svata

    CBFalconer Guest

    svata wrote:
    >
    > I always use google to search an answer, but often results are not
    > relevant.
    >
    >> I agree with what you've said, but the OP should also read section
    >> 6 of the comp.lang.c FAQ before posting back here. Section 6
    >> includes ways of dynamically allocating space for things that work
    >> like 2D arrays. The FAQ can be found at http://c-faq.com/


    I'm sure you've been told this before, but DON'T TOP-POST. See the
    links in my sig below.

    --
    Some informative links:
    <news:news.announce.newusers
    <http://www.geocities.com/nnqweb/>
    <http://www.catb.org/~esr/faqs/smart-questions.html>
    <http://www.caliburn.nl/topposting.html>
    <http://www.netmeister.org/news/learn2quote.html>
    <http://cfaj.freeshell.org/google/>
     
    CBFalconer, Nov 9, 2006
    #10
  11. svata said:

    > Chris Dollin wrote:
    >
    > I learn by doing. So I will see what results I get.


    That's fine sometimes, but there are also times when it's best to learn from
    other people's knowledge and experience. If you learn C "by doing", you're
    likely to end up doing lots of things that aren't correct, but which happen
    to behave in a particular way on your current system. Switch systems, and
    all your code breaks. Oops.

    Chris is an expert on C. Listen to Chris.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: normal service will be restored as soon as possible. Please do not
    adjust your email clients.
     
    Richard Heathfield, Nov 9, 2006
    #11
  12. svata

    Chris Dollin Guest

    Richard Heathfield wrote:

    > svata said:
    >
    >> Chris Dollin wrote:
    >>
    >> I learn by doing. So I will see what results I get.


    Something happend to your quoting, Richard: it looks like it was me that
    said "I learn by doing. So I will see what results I get.", but it was
    svata.

    (svata's quoting was misleading anyway, since he half-top-posted.)

    > That's fine sometimes, but there are also times when it's best to learn from
    > other people's knowledge and experience. If you learn C "by doing", you're
    > likely to end up doing lots of things that aren't correct, but which happen
    > to behave in a particular way on your current system. Switch systems, and
    > all your code breaks. Oops.
    >
    > Chris is an expert on C.


    I'd hesitate to describe myself so, since there's so much C I don't
    know (most of the C99 stuff, for example!) and I've used it in so
    few environments. I know /some/ stuff about C. I hope it's useful
    stuff.

    > Listen to Chris.


    But not when I'm singing.

    --
    Chris "for that, you want Annie, Rachel, Anne-Marie, or Tina." Dollin
    "Reaching out for mirrors hidden in the web." - Renaissance, /Running Hard/
     
    Chris Dollin, Nov 9, 2006
    #12
  13. svata

    CBFalconer Guest

    Chris Dollin wrote:
    > Richard Heathfield wrote:
    >

    .... snip ...
    >
    >> Listen to Chris.

    >
    > But not when I'm singing.


    Like me, you appear to be a member of the 'crows in heat' chorus.

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>
     
    CBFalconer, Nov 9, 2006
    #13
  14. svata

    Chris Dollin Guest

    CBFalconer wrote:

    > Chris Dollin wrote:
    >> Richard Heathfield wrote:
    >>

    > ... snip ...
    >>
    >>> Listen to Chris.

    >>
    >> But not when I'm singing.

    >
    > Like me, you appear to be a member of the 'crows in heat' chorus.


    Very likely. Or hedgehogs ... snuffling. Perhaps we should
    characterise Undefined Behaviour as "Chris or <your preferred
    abbreviation> will sing for/at you". /That/ will worry them
    more than hyperbolic nasal demons.

    --
    Chris "we are BRO-KEN, without FEE-LING" Dollin
    "Who do you serve, and who do you trust?" /Crusade/
     
    Chris Dollin, Nov 9, 2006
    #14
  15. Chris Dollin said:

    > Richard Heathfield wrote:
    >
    >> svata said:
    >>
    >>> Chris Dollin wrote:
    >>>
    >>> I learn by doing. So I will see what results I get.

    >
    > Something happend to your quoting, Richard:


    No, just a snip slip. Sorry about that.

    >> Chris is an expert on C.

    >
    > I'd hesitate to describe myself so,


    Think "relative". Compared to most OPs around here, you're a towering
    genius!

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: normal service will be restored as soon as possible. Please do not
    adjust your email clients.
     
    Richard Heathfield, Nov 9, 2006
    #15
  16. svata:

    > Hello Frederick,



    Hello svata :)


    > I know it doesn't make sense. I was wrong in my assumption.
    > I should use p_structure = (STRUCTURE **) malloc(FIRST *
    > sizeof(STRUCTURE*));
    >
    > but anyway... should rather use array of structures.
    >
    >
    > typedef structure {
    > code goes here...
    > } _structure;
    >
    > _structure *p_structure;



    One thing that you'll notice as you program more and more is that you'll
    come to use abbreviations (most programmers do in anyway). Humans love
    shortcuts. "should have" became "should've", which became "shuda". The
    words "until" and "because" are slowly but surely becoming "til" and
    "cause".

    When I myself define a pointer variable, I simply prefix "p" to the name; I
    used to put an underscore with it too but then more months passed by and I
    got lazier and lazier. The variable name "p_structure" is a bit of a
    mouthful, maybe you'd prefer to keep the names small.

    There are a few different prevalent coding styles out there. My own style
    works as follows:

    (1) Functions and Types start with a capital letter. If it consists of more
    than one word, than the next word starts with an initial capital, e.g.

    void TruncateLastFiveDigits(char*);

    (2) Objects start with a lower case letter. If it consists of more than one
    word, then underscores are used, e.g.

    int len_main_str = 34;

    (3) For a pointer, I prefix a simple "p" to the name where possible:

    void (*pFunc)(int) = Func;
    void (**ppFunc)(int) = &pFunc;

    int *pobj = &obj;
    int **ppobj = &pobj;
    int ***pppobj = &ppobj;

    (4) Macro names are in ALL CAPS. No other name should be written in ALL
    CAPS, e.g.:

    #define LEN 5
    #define SQR(x) ((x)*(x))

    Of course, this is just my own style. I'm not trying to shove it down your
    throat, but I'm just suggesting it as I thought you might like it.


    > // and then malloc()
    >
    > p_structure = malloc( INT * sizeof(_structure));
    >
    > if am I right?



    Yes, you're right. It's handy though to not have to repeat the name of the
    type:

    int *const p = malloc(5 * sizeof(int));

    can be written as:

    int *const p = malloc(5 * sizeof*p);

    Now, if we change the type to double, we only have to change "p":

    double *const p = malloc(5 * sizeof*p);

    Here's a taste of how I might write the code:

    #include <stddef.h> /* To use "size_t" */
    #include <stdlib.h> /* To use "malloc" and "free" */

    typedef struct MyStruct {
    int i;
    } MyStruct;

    size_t GetNumberFromSomewhere(void); /* Defined elsewhere */

    int main(void)
    {
    size_t const len = GetNumberFromSomewhere();

    MyStruct *const p = malloc(len * sizeof*p);

    /* ... */

    free(p);

    return 0;
    }

    --

    Frederick Gotham
     
    Frederick Gotham, Nov 9, 2006
    #16
  17. svata

    Flash Gordon Guest

    svata wrote:

    Please do not top post. Your reply belongs under the text you are
    replying to, not above.

    > svata
    >> I agree with what you've said, but the OP should also read section 6 of
    >> the comp.lang.c FAQ before posting back here. Section 6 includes ways of
    >> dynamically allocating space for things that work like 2D arrays. The
    >> FAQ can be found at http://c-faq.com/


    > I always use google to search an answer, but often results are not
    > relevant.


    I did not suggest using Google, I suggested a specific resource and a
    particular area in it. From another post here it is obvious you have not
    followed that advice, and if you don't bother following advice or
    posting properly I see no reason to bother giving you advice.
    --
    Flash Gordon
     
    Flash Gordon, Nov 9, 2006
    #17
  18. svata

    CBFalconer Guest

    Frederick Gotham wrote:
    >

    .... snip ...
    >
    > One thing that you'll notice as you program more and more is that
    > you'll come to use abbreviations (most programmers do in anyway).
    > Humans love shortcuts. "should have" became "should've", which
    > became "shuda". The words "until" and "because" are slowly but
    > surely becoming "til" and "cause".


    Not the smarter ones. They try to stick to English, and remain
    fairly clear to their readers. Should've is legitimate English,
    shuda is an execresence. Misuse of the word 'cause' causes nothing
    but confusion.

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>
     
    CBFalconer, Nov 9, 2006
    #18
  19. Chris Dollin <> writes:
    [...]
    > If you /must/ use a typedef for a structure -- you don't
    > need to, and some wise people argue that you shouldn't
    > (although others argue that those arguments aren't
    > convincing) -- you should also give it a /sensible/
    > name. "structure" isn't.
    >
    > typedef struct yourStructTagHere
    > {
    > int x;
    > int y;
    > } Point;


    There's also no need to use different identifiers for the struct tag
    and the typedef name:

    typedef struct Point {
    int x;
    int y;
    } Point;

    Now you can refer to the type either as "Point" or as "struct Point".

    The purpose of the typedef is to allow you to use a single identifer
    to refer to the type. The argument Chris alluded to above *against*
    using a typedef is that gives a second name to a type that already has
    a perfectly good name. For example, I would have declared it as:

    struct Point {
    int x;
    int y;
    };

    and just refer to the type as "struct Point".

    But plenty of smart people prefer to use the typedef. And if your
    structure doesn't contain any pointers to itself (as for a linked list
    node, for example), you don't need the struct tag:

    typedef struct {
    int x;
    int y;
    } Point;

    The drawback of this is that the name "Point" doesn't become visible
    until the end of the declaration, so you can't declare a member of
    type Point*.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 9, 2006
    #19
  20. Keith Thompson said:

    > Chris Dollin <> writes:
    > [...]
    >> If you /must/ use a typedef for a structure -- you don't
    >> need to, and some wise people argue that you shouldn't
    >> (although others argue that those arguments aren't
    >> convincing) -- you should also give it a /sensible/
    >> name. "structure" isn't.
    >>
    >> typedef struct yourStructTagHere
    >> {
    >> int x;
    >> int y;
    >> } Point;

    >
    > There's also no need to use different identifiers for the struct tag
    > and the typedef name:
    >
    > typedef struct Point {
    > int x;
    > int y;
    > } Point;


    It's true that there's no C reason to use different identifiers, but I do so
    anyway because it helps Microsoft's "Intellisense" to work out what you
    mean when you hit the button that says "take me to your definition". Not
    that I use Microsoft C terribly often - but when I do, I usually end up
    thanking myself for using a unique tag name. My preferred style nowadays
    is:

    struct foo_
    {
    char coal;
    short wait;
    unsigned letter;
    long time;
    float away;
    double trouble;
    bar baz;
    ad nauseam;
    };

    typedef struct foo_ foo;

    <snip>

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: normal service will be restored as soon as possible. Please do not
    adjust your email clients.
     
    Richard Heathfield, Nov 9, 2006
    #20
    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. michi

    Array of structures

    michi, Nov 18, 2004, in forum: C++
    Replies:
    8
    Views:
    524
    Andrey Tarasevich
    Nov 19, 2004
  2. tweak
    Replies:
    14
    Views:
    2,798
    Eric Sosman
    Jun 11, 2004
  3. Alfonso Morra
    Replies:
    11
    Views:
    733
    Emmanuel Delahaye
    Sep 24, 2005
  4. valerio
    Replies:
    3
    Views:
    377
  5. Amit  Limaye
    Replies:
    4
    Views:
    463
    Phlip
    Apr 10, 2006
Loading...

Share This Page