Velocity Reviews > Realloc() with 2D arrays; returning multiple values

# Realloc() with 2D arrays; returning multiple values

Anthony
Guest
Posts: n/a

 08-06-2003
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/

Eric Sosman
Guest
Posts: n/a

 08-06-2003
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.

--
http://www.velocityreviews.com/forums/(E-Mail Removed)

Samuel Barber
Guest
Posts: n/a

 08-06-2003
Eric Sosman <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> 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

Jens Schicke
Guest
Posts: n/a

 08-07-2003
Anthony <(E-Mail Removed)> 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.

Anthony
Guest
Posts: n/a

 08-07-2003
Eric Sosman <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> 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/