function returning pointer array 
Author Message
 function returning pointer array

Hello there,
I 'm trying to write a function which takes no argument (well that's easy) and
returns a pointer array. I don't have code to show you because I don't know how
to start :-( It seems that I cannot distinguish between char *foo[] and char
**foo. Any help about my function matter and the two dcls?

D.

--
PGP key 39A40276 at < http://www.*-*-*.com/ >
key fingeprint: 9A0B 61C6 B826 4B73 69BB  972B C5E7 A153 39A4 0276



Thu, 30 Jun 2005 06:50:35 GMT  
 function returning pointer array

Quote:

> Hello there,
> I 'm trying to write a function which takes no argument (well that's
> easy) and returns a pointer array. I don't have code to show you
> because I don't know how to start :-(

Well, you could probably try ugly things like:

        char *
        (foo(void))[]
        {
                ...
        }

but this isn't really something that works.  Functions can't return
`arrays'.  They can allocate chunks of memory, store array data in
there and return pointers to them though using something like:

        char **
        foo(void)
        {
        }

Quote:
> It seems that I cannot distinguish between char *foo[] and char
> **foo. Any help about my function matter and the two dcls?

There are a few differences, but you'd have to tell us more about the
specific application and why `char **' is not good enough for you.


Thu, 30 Jun 2005 07:00:31 GMT  
 function returning pointer array
On 11 Jan 2003 22:50:35 GMT, in comp.lang.c , Dimitris Mandalidis

Quote:

>Hello there,
>I 'm trying to write a function which takes no argument (well that's easy) and
>returns a pointer array.

You can't return an array, because you can't assign to one. You can
return a pointer though.....

Quote:
> I don't have code to show you because I don't know how
>to start :-( It seems that I cannot distinguish between char *foo[] and char
>**foo.

... which explains why you have this problem, I suspect.

Quote:
>Any help about my function matter and the two dcls?

You will need to return a char**.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>



Thu, 30 Jun 2005 07:01:44 GMT  
 function returning pointer array
On 12 Jan 2003 01:00:31 +0200, Giorgos Keramidas wrote

Quote:
> There are a few differences, but you'd have to tell us more about the
> specific application and why `char **' is not good enough for you.

Well it was a stupid question, since :

char *foo;

And foo is a pointer to the first element of an array, I suppose that :

char **foo;

Foo must be a pointer to the first element of an array which is an array by
itself. I believed I 've clarified this. The problem is that I don't know how to
`play' with them :

#include <stdio.h>

char **foo(void);

main()
{
        char **list;
        int i = 0;
        list = foo();
        while (*list++ != NULL)
        {
                printf("%s\n", list);
        }

Quote:
}

char **foo(void)
{
        char **list = { "fdsf", "FSDFew", NULL };
        return list;

Quote:
}

This gives :

test.c: In function `foo':
test.c:18: warning: initialization from incompatible pointer type
test.c:18: warning: excess elements in scalar initializer
test.c:18: warning: (near initialization for `list')
test.c:18: warning: excess elements in scalar initializer
test.c:18: warning: (near initialization for `list')

Any help?

D.

--
PGP key 39A40276 at <http://www.keyserver.net>
key fingeprint: 9A0B 61C6 B826 4B73 69BB  972B C5E7 A153 39A4 0276



Thu, 30 Jun 2005 07:32:40 GMT  
 function returning pointer array

Quote:

> char **foo(void)
> {
>    char **list = { "fdsf", "FSDFew", NULL };
>    return list;
> }

A declaration of the form:

        char **list;

allocates space in the memory of your computer for `list' and only for
that.  You can't initialise it like an array, because it's not an array.

Quote:
> This gives :

> test.c: In function `foo':
> test.c:18: warning: initialization from incompatible pointer type

This is what this warning is all about.

Another possible source of problems is that foo() attempts to return
the contents of a local variable.  This variable exists only in the
scope of the function foo() and the caller of foo() can not safely use
the pointer that foo() will return.  A better way to do this would be
to allocate `list' dynamically, in which case the scope of the memory
area pointed at by `list' will not be limited by the body of the
function:

        char **
        foo(void)
        {
                char **list;

                list = malloc(3 * sizeof(char *));
                if (list == NULL)
                        return NULL;

                list[0] = "fdsf";
                list[1] = "FSDFew";
                list[2] = NULL;
                return list;
        }

but then the caller should take care to do two things:

        a) To check that the value returned from foo() is non-NULL.
        b) To free the allocated array when it's done.



Thu, 30 Jun 2005 07:49:53 GMT  
 function returning pointer array
On 12 Jan 2003 01:49:53 +0200, Giorgos Keramidas wrote

Quote:
>         char **
>         foo(void)
>         {
>                 char **list;

>                 list = malloc(3 * sizeof(char *));
>                 if (list == NULL)
>                         return NULL;

>                 list[0] = "fdsf";
>                 list[1] = "FSDFew";
>                 list[2] = NULL;
>                 return list;
>         }

But `return list' always returns NULL as list finally points to list[2], am I
right? Perhaps I should allocate memory firstly for a char **buffer, assign its
address to char **list (list = buffer) and then play with list contents but I
don't know how, it seemed simple with simple pointers or it's too late :-)

Any help?
D.

--
PGP key 39A40276 at <http://www.keyserver.net>
key fingeprint: 9A0B 61C6 B826 4B73 69BB  972B C5E7 A153 39A4 0276



Thu, 30 Jun 2005 08:16:03 GMT  
 function returning pointer array

Quote:

> On 12 Jan 2003 01:49:53 +0200, Giorgos Keramidas wrote
> >         char **
> >         foo(void)
> >         {
> >                 char **list;

> >                 list = malloc(3 * sizeof(char *));
> >                 if (list == NULL)
> >                         return NULL;

> >                 list[0] = "fdsf";
> >                 list[1] = "FSDFew";
> >                 list[2] = NULL;
> >                 return list;
> >         }

> But `return list' always returns NULL as list finally points to list[2],
> am I right?

Sorry but no.  You've missed the [0], [1] and [2] above...


Thu, 30 Jun 2005 08:40:45 GMT  
 function returning pointer array


Quote:
>char *foo;

>And foo is a pointer to the first element of an array, I suppose that :

>char **foo;

>Foo must be a pointer to the first element of an array which is an array by
>itself. ...

This is very confusing.

Try drawing pictures.  Get yourself a piece of paper and draw some
boxes and arrows on it:

    +---------+     +-----+-----+-----+-----+
    |   p1   -----> | 'a' | 'b' | 'c' | '\0'|
    +---------+     +-----+-----+-----+-----+
                                         ^
                                         |
                                    +---------+
                                    |   p2    |
                                    +---------+

Here p1 and p2 are "char *" pointers.  p1 points to the first of
four "char"s, while p2 points to just one "char" (which happens
also to be the last of those four "char"s that p1 points to, but
so what?).  (I made the pointer boxes "bigger" than the char
boxes since sizeof(char *) is usually greater than 1.  Here it
does not really matter, but you might want to do the same.)

Note that an "array" is just a long sequence of boxes that all
{*filter*}up against each other.  A pointer is just a box containing
an arrow

Now draw more boxes for "char **".  A "char **" is a pointer that
points to another pointer.  We can make one that points to p2:

                   +---------+      +---------+
                   |    q   ------> |   p2    |
                   +---------+      +---------+

What you have on paper now is a model for this:

    char *p1 = "abc";
    char *p2 = p1 + 3;
    char **q = &p2;

Clearly this has not yet solved your problem, but at the same time,
you can see what "q" is *not* a "pointer to the first element of
an array" at all.  On the other hand, it *could* be (or become)
such a pointer -- if only you had an array whose first element
was around to be pointed-to.

First, though, you will need to draw that array, of the kinds of
things that "char **" can point to, i.e., of "char *"s:

    char *xx[3]; /* declare xx as array 3 of pointer to char */

    +---------+---------+---------+
    |   xx0   |   xx1   |   xx2   |
    +---------+---------+---------+

These three boxes have no initial values, so their arrows (they
are pointers so they hold arrows) are not pointing anywhere in
particular -- you need to set each one, just like you needed to
set p1 and p2 to point somewhere.  But now you have the array --
the set of boxes in a row -- that "q" can point to, so now you
can point q to it:

    q = &xx[0]; /* or q = xx */

If you then set each xx[i] to a valid pointer value -- draw some
more boxes on your paper as needed here -- then q will point to
the first of three pointers, each of which will point to a char,
or the first of some number of chars.  Since q points to xx[0],
instead of saying xx[0] = "some valid value", you can also say:
q[0] = "some valid value".

Finally, as you are scribbling boxes on paper, remember two things:

  - You "create" boxes by creating objects in memory.

  - When you return from a function, all its automatic objects
    ("local variables") are destroyed.  The value you return is
    copied to a temporary box first, but any remaining boxes
    that "belong to" that function should be scribbled-out on
    the paper.

If you want a "permanent" box, you must use a variable that has
the static storage class -- such as one declared outside a function,
or declared using the "static" keyword within a function.  In this
case you only get the one object, so a function that returns the
address of a "static" variable is somewhat dangerous.  (The ANSI
C "ctime" function is like this -- it returns the address of some
static-duration array of "char"s.  A later call to ctime() overwrites
the contents of the array, even if you are still using a pointer
to that array.)

If you want a box that is "semi-permanent" -- that lasts until you
explicitly say, "scribble this one out" -- you can use the malloc()
function.  Calling malloc() gets you a box, or a sequence of adjacent
boxes, with no initial values as usual; it returns a pointer to
the box, or the first of the sequence of boxes.  Those boxes are
good until you call free() and pass it the same value you got back
from malloc().  The free() function is what scribbles them out.

So, instead of "q = &xx[0]" to make q point to the first of three
boxes of the right size, you can also do:

    q = malloc(3 * sizeof *q);

This asks for "3 boxes of the right size" and, as long as malloc()
itself has not run out of memory, gives you a pointer to the first
of those three.  As with the xx[] array, those three boxes have no
initial values -- so you better give them some, perhaps using
malloc() again:

    if (q == NULL) ... handle the error ...
    q[0] = malloc(5 * sizeof *q[0]);

Note that always this fits the same pattern:
    var = malloc(N * sizeof *var);
gets you N boxes of the right size.  Leaving out N is the same
as using "1 *", i.e., gets you one box of the right size.  As
always you must also check for NULL:

    if (q[0] == NULL) ...
    q[1] = malloc(8 * sizeof *q[1]);
    if (q[1] == NULL) ...
    q[2] = malloc(3 * sizeof *q[2]);
    if (q[2] == NULL) ...

Of course, you can use a loop:

    for (i = 0; i < 3; i++) {
        q[i] = malloc(length[i] * sizeof *q[i]);
        if (q[i] == NULL) ...
    }

Note that I used a different length for each q[i] -- 5, 8, and 3
respectively -- so as long as malloc() does not run out of memory
and return NULL, each q[i] points to the first of a different number
of boxes.  This means that q[i][j] is valid for different values
of j depending on the value of i.  If you choose, you can instead
make each length the same.  In this case, q will act just like a
"two-dimensional" array.  If they are different, q will act like
a "ragged" array.  Of course, on your paper -- you HAVE been drawing
all this, right? :-) -- you will always be able to see just how
much each q[i] points to.  Unfortunately, there is no C function
to ask "how big is this thing I got from malloc()?".  Instead, if
you need those numbers in your code (rather than on your paper),
you will have to record them yourself as you allocate them.

Finally, note that you can even sum up all the lengths you want
at once, and malloc() that much space in one swoop.  If we want
"5, 8, and 3" we can just calculate 5+8+3 = 16, and do this:

    q[0] = malloc(16 * sizeof *q[0]);
    if (q[0] == NULL) ...

This time, we draw one 16-long-group of boxes on the paper.
Having done that, we can use pointer arithmetic to make q[1]
and q[2] point to places within this 16-long group, just as
p1 and p2 (remember them?) point into the same 4-element array
of "char"s.  Just do:

    q[1] = q[0] + 5;
    q[2] = q[1] + 8;

and draw, on your paper, the appropriate arrows.

(If you actually sit down and do this exercise, your understanding
of C pointers will grow by leaps and bounds.  If you just read this
article, it will not stick as well.  Try it with pencil and paper
-- or marker and whiteboard, or whatever you have handy.  It really
is a worthwhile exercise.)
--
In-Real-Life: Chris Torek, Wind River Systems (BSD engineering)
Salt Lake City, UT, USA (4039.22'N, 11150.29'W)

(you probably cannot email me -- spam has effectively killed email)



Thu, 30 Jun 2005 08:31:47 GMT  
 function returning pointer array
On 11 Jan 2003 23:32:40 GMT, in comp.lang.c , Dimitris Mandalidis

Quote:

>On 12 Jan 2003 01:00:31 +0200, Giorgos Keramidas wrote

>> There are a few differences, but you'd have to tell us more about the
>> specific application and why `char **' is not good enough for you.

>Well it was a stupid question, since :

>char *foo;

>And foo is a pointer to the first element of an array,

NO. foo is a pointer to a char. You can point it at a block of chars,
and treat it like an array, but it IS NOT.

Quote:
>I suppose that :

>char **foo;

>Foo must be a pointer to the first element of an array which is an array by
>itself.

No, foo is a pointer to a pointer to a char.

Quote:
>char **foo(void);

>main()
>{
>    char **list;
>    int i = 0;
>    list = foo();

ok, foo returns a char**

Quote:
>    char **list = { "fdsf", "FSDFew", NULL };

list has to point at a char pointer. if that happens to be an array of
pointers, then each one must be a char pointer.

NULL is not a char pointer. you mean "\0" or possibly just ""

Quote:
>test.c: In function `foo':
>test.c:18: warning: initialization from incompatible pointer type

this is the real error.

Quote:
>test.c:18: warning: excess elements in scalar initializer
>test.c:18: warning: (near initialization for `list')
>test.c:18: warning: excess elements in scalar initializer
>test.c:18: warning: (near initialization for `list')

these ones are just subsequent noise because of the first error

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>



Thu, 30 Jun 2005 09:10:04 GMT  
 function returning pointer array
On 12 Jan 2003 00:16:03 GMT, in comp.lang.c , Dimitris Mandalidis

Quote:

>On 12 Jan 2003 01:49:53 +0200, Giorgos Keramidas wrote

>>         char **
>>         foo(void)
>>         {
>>                 char **list;

>>                 list = malloc(3 * sizeof(char *));
>>                 if (list == NULL)
>>                         return NULL;

>>                 list[0] = "fdsf";
>>                 list[1] = "FSDFew";
>>                 list[2] = NULL;
>>                 return list;
>>         }

>But `return list' always returns NULL as list finally points to list[2], am I
>right?

No. list points to the block of memory malloced. After assigning it
you never change its value, only its contents. list[2] points to the
3rd element of list, which contains NULL, but thats irrelevant since
you return list.

Quote:
>Perhaps I should allocate memory firstly for a char **buffer, assign its
>address to char **list (list = buffer)

pointless - if they're the same type, they behave in the same way.

Quote:
>and then play with list contents but I
>don't know how, it seemed simple with simple pointers or it's too late :-)

Think of a char** as a pointer to an array of char* if you have to,
then think of each char* as pointing to an array of char. Work with
each type separately. And then remember that array !=pointer

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>



Thu, 30 Jun 2005 09:12:53 GMT  
 function returning pointer array
On 11 Jan 2003 17:31:47 -0700, Chris Torek wrote

Quote:
> This time, we draw one 16-long-group of boxes on the paper.
> Having done that, we can use pointer arithmetic to make q[1]
> and q[2] point to places within this 16-long group, just as
> p1 and p2 (remember them?) point into the same 4-element array
> of "char"s.  Just do:

>     q[1] = q[0] + 5;
>     q[2] = q[1] + 8;

I believe I 've clarified this. q[1] is a pointer to a char (or to the first of
a bunch a chars) as well as q[0] and q[1]. After the first statement q[1] points
to what q[0] was pointing to + 5, and after the second statement q[2] points to
what q[1] was pointing to + 8 eg. if q[0], q[1], q[2] were all pointing to the
first char of a 16-byte string (array of chars), q[1] finally points to the
6th char (index == 5) of the 16-byte string to which q[0] was pointing to, and
q[2] finally points to the 9th element of 16-byte string to which q[1] was
pointing to. Despite I 'm not good at ASCII art :

char *q[3];
------
| q[0] ---> "abcdefghijklmnop"
------
------
| q[1] ---> "abcdefghijklmnop"
------
------
| q[2] ---> "abcdefghijklmnop"
------

And finally we have this :

-----
| q[0] ---> "abcdefghijklmnop"
-----             ^       ^
                  |       |
              --------  --------
              | q[1] |  | q[2] |
              --------  --------

But I' m still losing some point :-( Never mind, I have to do a revision to K&R
II chapter 5 before I step forward. Thanks all of you for your help.

D.

--
PGP key 39A40276 at <http://www.keyserver.net>
key fingeprint: 9A0B 61C6 B826 4B73 69BB  972B C5E7 A153 39A4 0276



Thu, 30 Jun 2005 22:13:52 GMT  
 function returning pointer array

Quote:

> Hello there,
> I 'm trying to write a function which takes no argument (well that's easy)
> and returns a pointer array. I don't have code to show you because I don't
> know how to start :-( It seems that I cannot distinguish between char
> *foo[] and char **foo. Any help about my function matter and the two dcls?

You can't distinguish between them because they're virtually identical.
There may be a few minor differences, I don't know. Anyway:

char **array(){
        const static char *stuff = "xyzzyplugh";
        char **arraytemp = malloc(strlen(stuff) * sizeof(char *));
        char *ptr = stuff;
        int i = 0;
        while(*ptr)
                arraytemp[i++] = *ptr++;
        return arraytemp;

Quote:
}

You'll get pointers to each character in the string. I did a more useful
example (a function to split an arbitrary string by an arbitrary delimiter
of any length). You may want to google for it.
--
Replace spamtrap with bd to reply.
The sheep died in the wool.


Fri, 01 Jul 2005 07:43:15 GMT  
 function returning pointer array
On Sun, 12 Jan 2003 23:43:15 GMT, in comp.lang.c , bd

Quote:


>> Hello there,
>> I 'm trying to write a function which takes no argument (well that's easy)
>> and returns a pointer array. I don't have code to show you because I don't
>> know how to start :-( It seems that I cannot distinguish between char
>> *foo[] and char **foo. Any help about my function matter and the two dcls?

>You can't distinguish between them because they're virtually identical.

I think not. Whats sizeof(foo) in each case?

Quote:
>There may be a few minor differences, I don't know.

Indeed!!

FWIW you're correct that they're identical in the context of a
function call, but only in that situation.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>



Fri, 01 Jul 2005 08:27:44 GMT  
 
 [ 13 post ] 

 Relevant Pages 

1. Pointer to function returning pointer to function returning...

2. Pointers: return of pointer to array of pointers to main

3. Returning pointer to array of structure from function

4. Arrays, Functions, and Returning Pointers via Parameters

5. Pointers, Arrays, and function returns

6. Returning and manipulating array/pointer from function to main

7. Returning Int array pointers from functions

8. Question about signal()/pointers to functions that return pointers to functions

9. Function returns pointer to dynamic array

10. function pointers and function pointers array

11. Can function returning pointer return negative integers?

12. Returning Pointer To Pointer From Function

 

 
Powered by phpBB® Forum Software