Realloc() with 2D arrays; returning multiple values

A

Anthony

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/
 
E

Eric Sosman

Anthony said:
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.
 
S

Samuel Barber

Eric Sosman said:
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
 
J

Jens Schicke

Anthony said:
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.
 
A

Anthony

Eric Sosman said:
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/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top