Realloc() with 2D arrays; returning multiple values

Discussion in 'C Programming' started by Anthony, Aug 6, 2003.

  1. Anthony

    Anthony Guest

    Hello,

    I am writing a function that populates an array of pointers to
    strings. Both the number of strings in the array, and the lengths of
    the strings, are dynamic; in particular, the number of strings won't
    be known until just before the function returns.

    The problem is that in the calling function, I need to know both the
    address of the array, and the number of strings. My first thought was
    to pass a pointer to the array into the function, and return a size_t
    which is the number of strings. That way, I know the address of the
    array to begin with, and I get the number of strings when the function
    returns. But since I realloc() within the function, I change the
    address of the array, so the address in the calling function is no
    longer correct.

    At this point, I think that I'll need to create a structure to hold
    both the array and the number of strings, and return a pointer to an
    instance of the struct.

    Is my thinking correct on this? Is there a different/better approach?

    Thanks,
    Anthony
    http://nodivisions.com/
     
    Anthony, Aug 6, 2003
    #1
    1. Advertising

  2. Anthony

    Eric Sosman Guest

    Anthony wrote:
    >
    > Hello,
    >
    > I am writing a function that populates an array of pointers to
    > strings. Both the number of strings in the array, and the lengths of
    > the strings, are dynamic; in particular, the number of strings won't
    > be known until just before the function returns.
    >
    > The problem is that in the calling function, I need to know both the
    > address of the array, and the number of strings. My first thought was
    > to pass a pointer to the array into the function, and return a size_t
    > which is the number of strings. That way, I know the address of the
    > array to begin with, and I get the number of strings when the function
    > returns. But since I realloc() within the function, I change the
    > address of the array, so the address in the calling function is no
    > longer correct.
    >
    > At this point, I think that I'll need to create a structure to hold
    > both the array and the number of strings, and return a pointer to an
    > instance of the struct.
    >
    > Is my thinking correct on this? Is there a different/better approach?


    Unless you have a C99 compiler you're not going to be
    able to put the array itself inside a struct. But in any
    version of C you can put a pointer to the array inside the
    struct, viz:

    struct stringinfo {
    char **stringarray;
    size_t stringcount;
    };

    There's more than one way to use a gizmo of this kind,
    too. As you mention, the function could return a pointer
    to a struct like this. It could also just plain return the
    entire struct as its value:

    struct stringinfo func( /* args */ ) {
    struct stringinfo result;
    ...
    result.stringarray = ...;
    result.stringcount = ...;
    return result;
    }

    Still another possibility is to have the caller create the
    struct, pass a pointer to it as one of the function arguments,
    and let the function fill in the fields:

    void func(struct stringinfo *info, /* other args */ ) {
    ...
    info->stringarray = ...;
    info->stringcount = ...;
    }

    If you examine this last method closely, you'll see that
    the struct packaging really isn't necessary; it's just a
    shorthand way of passing two arguments in one "slot." You
    could instead just pass pointers to the individual items:

    void func(char ***stringarray, size_t *stringcount,
    /* other args */ ) {
    ...
    *stringarray = ...;
    *stringcount = ...;
    }

    And then there are mixed strategies, where the function
    returns one datum as its value and modifies the other through
    a pointer in the argument list, e.g.

    char **func(size_t *stringcount, /* other args */ ) {
    char **stringarray;
    ...
    *stringcount = ...;
    return stringarray;
    }

    Personally, I'd usually prefer one of the struct-packaged
    variants, because it seems comforting to keep the "thing" and
    the "description" (the array and the element count) together
    rather than letting them float around at random. But that's
    mostly a matter of taste and/or whim, and I myself sometimes
    choose a different method.

    --
     
    Eric Sosman, Aug 6, 2003
    #2
    1. Advertising

  3. Eric Sosman <> wrote in message news:<>...
    > Unless you have a C99 compiler you're not going to be
    > able to put the array itself inside a struct.


    Actually, there's a good chance his compiler does support this. It's a
    common extension to ANSI C.

    Sam
     
    Samuel Barber, Aug 7, 2003
    #3
  4. Anthony

    Jens Schicke Guest

    Anthony <> wrote:
    > Hello,
    >
    > I am writing a function that populates an array of pointers to
    > strings. Both the number of strings in the array, and the lengths of
    > the strings, are dynamic; in particular, the number of strings won't
    > be known until just before the function returns.
    > ...
    > Is my thinking correct on this? Is there a different/better approach?
    >


    Maybe you should try a completely other approach to the problem:
    Try not to put the pointers into an array but to build a tree of some
    kind. Then you can easily pass the pointer of the root node, and have the
    return value free for error codes. If this approach is usefull of course
    depends upon the performance you want at accessing the array/tree later.
     
    Jens Schicke, Aug 7, 2003
    #4
  5. Anthony

    Anthony Guest

    Eric Sosman <> wrote in message news:<>...
    > Unless you have a C99 compiler you're not going to be
    > able to put the array itself inside a struct. But in any
    > version of C you can put a pointer to the array inside the
    > struct


    Sorry for not being clear; I was saying "array" and meaning "pointer"
    but I know they're not really the same thing. But yes, I meant to
    store a pointer in the struct.

    > Still another possibility is to have the caller create the
    > struct, pass a pointer to it as one of the function arguments,
    > and let the function fill in the fields:
    >
    > void func(struct stringinfo *info, /* other args */ ) {
    > ...
    > info->stringarray = ...;
    > info->stringcount = ...;
    > }


    This was what I'd planned to do.

    > If you examine this last method closely, you'll see that
    > the struct packaging really isn't necessary; it's just a
    > shorthand way of passing two arguments in one "slot." You
    > could instead just pass pointers to the individual items:
    >
    > void func(char ***stringarray, size_t *stringcount,
    > /* other args */ ) {
    > ...
    > *stringarray = ...;
    > *stringcount = ...;
    > }


    Ah, now that's something that I didn't realize. I can pass a pointer
    to the _count_ because that won't get moved by a realloc(). Then
    modify that directly, and send the new array pointer as the return
    value.

    > And then there are mixed strategies, where the function
    > returns one datum as its value and modifies the other through
    > a pointer in the argument list, e.g.
    >
    > char **func(size_t *stringcount, /* other args */ ) {
    > char **stringarray;
    > ...
    > *stringcount = ...;
    > return stringarray;
    > }


    Oh. You already said all that :)

    > Personally, I'd usually prefer one of the struct-packaged
    > variants, because it seems comforting to keep the "thing" and
    > the "description" (the array and the element count) together
    > rather than letting them float around at random. But that's
    > mostly a matter of taste and/or whim, and I myself sometimes
    > choose a different method.


    I think I'll try the pointer-to-the-count method first, instead of
    using a struct, and see how that goes. Maybe I'll switch to the
    struct method if it doesn't work out, or if the first method is so
    easy that it isn't fun enough. Thanks a bunch for the help.

    -Anthony
    http://nodivisions.com/
     
    Anthony, Aug 7, 2003
    #5
    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. Alexandra Stehman
    Replies:
    5
    Views:
    30,908
    Chris Smith
    Jun 17, 2004
  2. Jeremy Watts
    Replies:
    3
    Views:
    971
    Jeremy Watts
    May 24, 2005
  3. WL
    Replies:
    9
    Views:
    525
    Al Bowers
    Jul 15, 2003
  4. Philipp
    Replies:
    21
    Views:
    1,187
    Philipp
    Jan 20, 2009
  5. Joshua Muheim
    Replies:
    8
    Views:
    216
    Dejan Dimic
    Nov 23, 2007
Loading...

Share This Page