pointer to NULL terminated array of pointer

K

kpamafrederic

Hi all,

I have a little question regarding the subject of the topic. Sorry if it's seems like a silly question but I never really studied C and my knowledge comes from personal projects so I do need to learn.

Currently I'm trying to pass an return a pointer to an array of pointer andI wanted to know how I can correctly implement it. Basically the function is supposed to look into a Database and return all string results in a pointer. Since the caller doesn't know how many results the function will return I was thinking of something like this (note that it is how I implemented it):

int foo( char ***results);

then the caller can walk through the result with something like this :

char **results;
int i=0;

foo(&results);

while ( results != 0 )
{
// do something with this entry.
i++;
}

But I found the prototype of foo not really "self-explanatory". I also thought of something like this :

int foo ( char *result[]);

but I supposed this would means that the result is *const*ant while the user is in charge of freeing the results.

Can somebody explain me how he would've done it please? Thanks you so much for your time.
 
F

Fred K

Hi all, I have a little question regarding the subject of the topic. Sorry if it's seems like a silly question but I never really studied C and my knowledge comes from personal projects so I do need to learn. Currently I'm trying to pass an return a pointer to an array of pointer and I wanted to know how I can correctly implement it. Basically the function is supposed tolook into a Database and return all string results in a pointer. Since thecaller doesn't know how many results the function will return I was thinking of something like this (note that it is how I implemented it): int foo( char ***results); then the caller can walk through the result with something like this : char **results; int i=0; foo(&results); while ( results != 0 ) { // do something with this entry. i++; } But I found the prototype of foo not really "self-explanatory". I also thought of something like this : int foo ( char *result[]); but I supposed this would means that the result is *const*ant while the user is in charge of freeing the results. Can somebody explain me how he would've done it please? Thanks you so much for your time.


Your function "foo" is declared to return an int, but you never yse it. Whynot return the number of strings there?

Other possibilities:

char **names;
int numNames;

foo( &names, &numNames );
with "void foo( char ***names, int *num)"

names = foo( &num);
with "char **foo( int *numNames )"

In all of these cases it is unnecessary to include a sentinel in the array.Also, think about some instance where there is an actual null string in the middle of the array.
 
E

Eric Sosman

Hi all,

I have a little question regarding the subject of the topic. Sorry if it's seems like a silly question but I never really studied C and my knowledge comes from personal projects so I do need to learn.

Currently I'm trying to pass an return a pointer to an array of pointer and I wanted to know how I can correctly implement it. Basically the function is supposed to look into a Database and return all string results in a pointer. Since the caller doesn't know how many results the function will return I was thinking of something like this (note that it is how I implemented it):

int foo( char ***results);

then the caller can walk through the result with something like this :

char **results;
int i=0;

foo(&results);

while ( results != 0 )
{
// do something with this entry.
i++;
}

But I found the prototype of foo not really "self-explanatory". I also thought of something like this :

int foo ( char *result[]);

but I supposed this would means that the result is *const*ant while the user is in charge of freeing the results.


Not sure where the notion of "*const*ant" comes from. This
declaration is equivalent to

int foo(char **result);

.... which as you see is not the same as the original, not at all.
Can somebody explain me how he would've done it please? Thanks you so much for your time.


I'd probably have returned the pointer as the function's value:

char **foo(void) {
...
return pointer_to_0th_string_pointer;
}
...
char **results = foo();

If anything went wrong, foo() could return NULL to report the
failure. Also, I'd have something like freefoo(char**) to release
all the memory; that way, the caller wouldn't need to know details
of how the memory was allocated (array of pointers to separately
allocated strings, array of pointers to adjacent strings in one
block, one omnibus block holding both the pointers and the strings,
whatever).

Your design has the advantage of being able to return more
status information than a mere NULL/!NULL can, but if "failed"
is enough and you don't need "failed because..." then returning
a pointer seems clearer. One way to get the simplicity of a
return value along with the flexibility of additional status
information is to return a struct:

struct {
int status;
char **result;
double phase_of_moon;
} foo_result;

struct foo_result foo(void) {
struct foo_result res;
...
res.status = ...;
res.result = ...;
res.phase_of_moon = ...;
return res;
}
...
struct foo_result gotcha = foo();
if (gotcha.status < 0) report_error_and_die(gotcha.status);
for (i = 0; res.result != NULL; ++i) {
...

There are other variations, too, but these should get you
started.
 
B

Barry Schwarz

Hi all,

I have a little question regarding the subject of the topic. Sorry if it's seems like a silly question but I never really studied C and my knowledge comes from personal projects so I do need to learn.

Currently I'm trying to pass an return a pointer to an array of pointer and I wanted to know how I can correctly implement it. Basically the function is supposed to look into a Database and return all string results in a pointer. Since the caller doesn't know how many results the function will return I was thinking of something like this (note that it is how I implemented it):

int foo( char ***results);

then the caller can walk through the result with something like this :

char **results;
int i=0;

foo(&results);

while ( results != 0 )
{
// do something with this entry.
i++;
}

But I found the prototype of foo not really "self-explanatory". I also thought of something like this :

int foo ( char *result[]);


When used to declare the parameter of a function, char *result[] is
IDENTICAL to char **result. As you can see, this is not the same as
your first prototype for foo().
but I supposed this would means that the result is *const*ant while the user is in charge of freeing the results.

Why do you think result would be constant. Since it is a parameter,
it is passed by value. Therefore any change you make to it will
disappear as soon as the function returns. On the other hand, any
change you make to the object this pointer points to live as long as
the object does.

Freeing memory applies only to allocated memory. If your function
allocates memory without freeing it, then it is the responsibility of
the calling function to eventually perform the clean up. It has
nothing to do with the form of your parameter.
Can somebody explain me how he would've done it please? Thanks you so much for your time.

My personal preference: Rather than have foo remember to dereference
the parameter each time, I would define a local char**, allocate (and
possibly reallocate) memory to hold all the pointers to strings I need
(this is effectively an array of pointers), and allocate memory for
each string pointer to point to. When all done and in keeping with
your subject, I would add one more pointer to string at the end of the
array and set it to NULL. When all processing is complete, foo would
return the value in the char** (instead of int as you have it).

In the calling function, the call to foo would be in an assignment
statement setting a local char** to the starting address of the array
of pointers built by foo. After processing each pointer in the array,
I would free it. (Alternately, I might wait until after processing
all the pointers to free them in a fairly tight loop.) In either
case, only after freeing each string would I then free the array
itself (whose address is in my local char**).
 
K

kpamafrederic

Thanks for your replies.

Actually, like Eric remarked I chose this way to return an error code like sql error, no memory etc... But all those ideas makes sense.

In fact Eric I have a problem with the hole "const" thing so I should ask you now : When I said that the *names[] would means a pointer to constant it's because I came to the conclusion that the array specifier means that thevalues into it are constants. Maybe I'm wrong?
 
E

Eric Sosman

Thanks for your replies.

Actually, like Eric remarked I chose this way to return an error code like sql error, no memory etc... But all those ideas makes sense.

In fact Eric I have a problem with the hole "const" thing so I should ask you now : When I said that the *names[] would means a pointer to constant it's because I came to the conclusion that the array specifier means that the values into it are constants. Maybe I'm wrong?

As Barry Schwarz says, in a function's parameter list anything
that looks like an array gets turned into a pointer to that array's
element type:

foo(char array[]) ==> foo(char *array)
foo(int *array[]) ==> foo(int **array)
foo(char **long[42]) ==> foo(long ***array)

(In the third example, not even the "42" survives. There's a
special case `foo(double array[static 42])', but even that
doesn't change things much: inside the function, `array' is
still of type `double*'.)

Section 6 of the comp.lang.c Frequently Asked Questions
(FAQ) page at <http://www.c-faq.com/> has more information on
this and related issues.
 
K

kpamafrederic

When used to declare the parameter of a function, char *result[] is

IDENTICAL to char **result. As you can see, this is not the same as

your first prototype for foo().

Yes. This is because I lost myself in pointers ^^. I meant **result[]. But note that your Idea :

Why do you think result would be constant. Since it is a parameter,

it is passed by value. Therefore any change you make to it will

disappear as soon as the function returns. On the other hand, any

change you make to the object this pointer points to live as long as

the object does.

Ok so maybe I shouldn't pass an array as parameter (If I understood correctly what you meant!) Because note that :
Freeing memory applies only to allocated memory. If your function

allocates memory without freeing it, then it is the responsibility of

the calling function to eventually perform the clean up. It has

nothing to do with the form of your parameter.

Yes the caller is supposed to free the memory.
My personal preference: Rather than have foo remember to dereference

the parameter each time, I would define a local char**, allocate (and

possibly reallocate) memory to hold all the pointers to strings I need

(this is effectively an array of pointers), and allocate memory for

each string pointer to point to. When all done and in keeping with

your subject, I would add one more pointer to string at the end of the

array and set it to NULL. When all processing is complete, foo would

return the value in the char** (instead of int as you have it).
Yes this is exactly what I tried to explain, sorry if I did not make myselfclear enough but the function is supposed to pass the results with the char **(*?) parameter. But I was wondering what's the best way to write the prototype of the function since with this solution in particular, there's no difference to tell that "char **" is in fact an *array* of pointer and not a simple string.

So basically my function write the pointer to the array of results in the destination of the pointer ( *results = found_results, found_results beingmalloced and freed by the caller)
 
E

Eric Sosman

[...]
As Barry Schwarz says, in a function's parameter list anything
that looks like an array gets turned into a pointer to that array's
element type:

foo(char array[]) ==> foo(char *array)
foo(int *array[]) ==> foo(int **array)
foo(char **long[42]) ==> foo(long ***array)

(Sigh.) Too much "editing for clarity" on that third example.
Should have been

foo(long **array[42]) ==> foo(long ***array)

Sorry for any confusion.
 
B

Barry Schwarz

When used to declare the parameter of a function, char *result[] is
IDENTICAL to char **result. As you can see, this is not the same as
your first prototype for foo().

Yes. This is because I lost myself in pointers ^^. I meant **result[]. But note that your Idea :
Why do you think result would be constant. Since it is a parameter,
it is passed by value. Therefore any change you make to it will
disappear as soon as the function returns. On the other hand, any
change you make to the object this pointer points to live as long as
the object does.

Ok so maybe I shouldn't pass an array as parameter (If I understood correctly what you meant!) Because note that :

I have no idea how you could infer that from my comment.

In your code, you didn't pass an array. You passed the address of an
indeterminate char**. (foo() set the value of the char** so the value
was no longer indeterminate when you used it.)

Even if you had tried to pass an array, the compiler would have
automatically converted it to a pointer. See my first comment
regarding function parameters.
Yes the caller is supposed to free the memory.

Yes this is exactly what I tried to explain, sorry if I did not make myself clear
enough but the function is supposed to pass the results with the char **(*?) parameter.

Your function can pass the result back to the calling program by
simply using *result. But since the value to be passed is a char**,
the parameter must be a char***.
But I was wondering what's the best way to write the prototype of the function
since with this solution in particular, there's no difference to tell that "char **" is
in fact an *array* of pointer and not a simple string.

A char** would never point to a string. It would always point to a
char*. That char* could point to a string but this is all irrelevant
to your question. When you pass a pointer to a function, there is
nothing in the C language or syntax that will tell the function how
many consecutive objects the pointer points to. In your case,
&results is the address of a single char**. You can store into
results using *result if foo() but you would be in serious trouble if
you would be in serious trouble if you tried to store into
*(result+1).

The fact that results is intended to point to an "array" of char* is
something foo has to know as part of its design. After allocating
space and storing the address in *result, you can assign values to
each of the allocated char* with an expression of the form
(*result), or the equivalent result[0] which I find easier on
the eyes.
So basically my function write the pointer to the array of results in the destination of the pointer ( *results = found_results, found_results being malloced and freed by the caller)

That is what you showed in the original post but you asked for other
options.
 

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