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.
--
Er*********@sun.com