![]() |
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. |
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. |
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 |
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 |
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? |
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 |
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) |
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 |
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 02:36 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.