You are not logged in.

#1 2006-10-14 18:27:10

T-Dawg
Forum Fellow
From: Charlotte, NC
Registered: 2005-01-29
Posts: 2,736

returning an array in C

I can't get a function to return an array in C. I have to following:

char *array(void)
{
        char *bla[3] = {"aaa", "bbb", "ccc"};
         return *bla;
}

int main(void)
{
     char *a = array();
 }

but when I call on array() in main I need its contents in the form of the array. This only gives me the first element.

Offline

#2 2006-10-14 19:37:04

bboozzoo
Member
From: Poland
Registered: 2006-08-01
Posts: 125

Re: returning an array in C

Penguin wrote:

I can't get a function to return an array in C. I have to following:

char *array(void)
{
        char *bla[3] = {"aaa", "bbb", "ccc"};
         return *bla;
}

int main(void)
{
     char *a = array();
 }

but when I call on array() in main I need its contents in the form of the array. This only gives me the first element.

First of all it works as the compiler placed your strings "aaa", "bbb" in data segment and you return a pointer to one of the strings present somewhere in memory on the stack. If the strings would be generated at runtime then you need to use a static buffer or pass a buffer as parameter

char *
array(void) {
  static char buff[20] = {};
  ...
}

or

int
array(char * buffer, size_t buffer_len) {
  ...
  // put string in callers buffer
}

but

char *
array(void) {
   char a[10];  // this buffer is created on stack!
   return a;
}

now if you happen to do anything that alters the stack after the call to this function, the buffer will be overwritten.
Thus, the convention is to use either flag any buffer as static/const or use buffer passed by caller.
Anyways in your case printf("%sn", array()) will print the whole contents that is "aaa".

Offline

#3 2006-10-14 19:41:33

codemac
Member
From: Cliche Tech Place
Registered: 2005-05-13
Posts: 794
Website

Re: returning an array in C

Penguin wrote:
char *array(void)
{
        char *bla[3] = {"aaa", "bbb", "ccc"};
         return *bla;
}

int main(void)
{
     char *a = array();
 }
char** array(void)
{
        char* bla[3] = {"aaa", "bbb", "ccc"};
         return bla;
}

int main(void)
{
     char **a = array();
 }

I'm not at my computer so I can't verify that it's right, but I'm pretty damn sure that's what you want.

Offline

#4 2006-10-14 19:47:20

woogie
Member
From: Ottawa, ON
Registered: 2005-04-01
Posts: 45

Re: returning an array in C

Penguin wrote:

I can't get a function to return an array in C. I have to following:

char *array(void)
{
        char *bla[3] = {"aaa", "bbb", "ccc"};
         return *bla;
}

int main(void)
{
     char *a = array();
 }

but when I call on array() in main I need its contents in the form of the array. This only gives me the first element.

Here's the deal: a char * is a pointer to a single char in memory. By incrementing or decrementing the pointer, you get pointed at other chars in memory. Check this out:

char * x = "Hello";
char[6] y = "Hello";

You can use x and y interchangeably after that point - they're both char pointers, and are pointing at two seperate points in memory with the same contents.

So to return an array of strings, what you want is an array of arrays, or in this case an array of pointers .... which is really a pointer to a pointer! (Confused yet?)

Now to further confuse you, you have another problem with your code: In the array method, you're allocating memory for your array directly on the stack. This means, as soon as your method exits, that space in memory won't be valid any more. So as soon as the method returns, the pointer you return will be useless.

So we need to include some dynamic memory allocation on the heap (getting complicated eh?). And then we need to copy strings into those spaces in memory. And then we'll be good to go. So here's what your simple code (unfortunately!) turns into:

#include <stdio>
#include <malloc>
#include <string>

char ** array(void)
{
        //Here we allocate enough memory for 3 _pointers_
        char ** bla = (char **) malloc (sizeof(char *) * 3);
        //Now, for each of those 3 pointers, we allocate memory
        //and copy in the string we want
        //Remember to leave room for the null character at the end of strings!
        bla[0] = (char *) malloc (sizeof(char) * 4);
        strcpy(bla[0], "aaa");
        bla[1] = (char *) malloc (sizeof(char) * 4);
        strcpy(bla[1], "bbb");
        bla[2] = (char *) malloc (sizeof(char) * 4);
        strcpy(bla[2], "ccc");
        //we don't want to return *bla, as that dereferences the pointer
        return bla;
}
int main(void)
{
        //we want a to be a pointer to more pointers
        char ** a = array();
        printf(a[0]);
        printf(a[1]);
        printf(a[2]);
        free(a[0]);
        free(a[1]);
        free(a[2]);
        free(a);
};

Offline

#5 2006-10-14 20:19:55

T-Dawg
Forum Fellow
From: Charlotte, NC
Registered: 2005-01-29
Posts: 2,736

Re: returning an array in C

Awsome thanks guys. The latter code worked perfect. Trying to relearn C and all this memory handling bussiness gets me.

Tyler

Offline

#6 2006-10-16 14:58:39

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: returning an array in C

this is the gross way to do it... personally, I would rewrite as follows:

#include <stdio>
#include <malloc>
#include <string>

void set_array(char **ret, int maxsize)
{
    strncpy(ret[0], "aaa", min(strlen("aaa"),maxsize-1));
    strncpy(ret[1], "bbb", min(strlen("bbb"),maxsize-1));
    strncpy(ret[2], "ccc", min(strlen("ccc"),maxsize-1));
}

int main(void)
{
    const int MAX_WORD_SIZE = 25;
    char **arr = (char**)calloc(MAX_WORD_SIZE * 3, sizeof(char));
    set_array(arr, MAX_WORD_SIZE);
    //do something
    free(arr);
};

Few notes: · calloc sets all bytes to 0 - this is very useful for strings which should be 0 terminated
· forcing you to allocate before you call the function indicates the need to free the memory yourself.  I always hated "someptr = foo(); free(someptr);"  as it provides no indication you should be freeing the memory, except in the man page somewhere.
· use of length-based functions (strncpy) helps prevent buffer overflow issues

Offline

Board footer

Powered by FluxBB