Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   pointer to NULL terminated array of pointer (http://www.velocityreviews.com/forums/t951612-pointer-to-null-terminated-array-of-pointer.html)

kpamafrederic@gmail.com 08-30-2012 09:02 PM

pointer to NULL terminated array of pointer
 
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[i] != 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.

Fred K 08-30-2012 09:44 PM

Re: pointer to NULL terminated array of pointer
 
On Thursday, August 30, 2012 2:02:43 PM UTC-7, kpamaf...@gmail.com wrote:
> 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[i] != 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.

Eric Sosman 08-30-2012 10:09 PM

Re: pointer to NULL terminated array of pointer
 
On 8/30/2012 5:02 PM, kpamafrederic@gmail.com wrote:
> 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[i] != 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[i] != NULL; ++i) {
...

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

--
Eric Sosman
esosman@ieee-dot-org.invalid

Barry Schwarz 08-30-2012 10:18 PM

Re: pointer to NULL terminated array of pointer
 
On Thu, 30 Aug 2012 14:02:43 -0700 (PDT), kpamafrederic@gmail.com
wrote:

>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[i] != 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**).

--
Remove del for email

kpamafrederic@gmail.com 08-30-2012 10:20 PM

Re: pointer to NULL terminated array of pointer
 
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?

Eric Sosman 08-30-2012 10:31 PM

Re: pointer to NULL terminated array of pointer
 
On 8/30/2012 6:20 PM, kpamafrederic@gmail.com wrote:
> 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.

--
Eric Sosman
esosman@ieee-dot-org.invalid

kpamafrederic@gmail.com 08-30-2012 10:35 PM

Re: pointer to NULL terminated array of pointer
 
On Friday, August 31, 2012 12:18:56 AM UTC+2, Barry Schwarz wrote:


> 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)


Eric Sosman 08-31-2012 01:16 AM

Re: pointer to NULL terminated array of pointer
 
On 8/30/2012 6:31 PM, Eric Sosman wrote:
> [...]
> 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.

--
Eric Sosman
esosman@ieee-dot-org.invalid

Barry Schwarz 08-31-2012 04:06 AM

Re: pointer to NULL terminated array of pointer
 
On Thu, 30 Aug 2012 15:35:23 -0700 (PDT), kpamafrederic@gmail.com
wrote:

>On Friday, August 31, 2012 12:18:56 AM UTC+2, Barry Schwarz wrote:
>
>> 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.

>> 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 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)[i], or the equivalent result[0][i] 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.

--
Remove del for email


All times are GMT. The time now is 01:53 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.