user967850
user967850

Reputation: 31

compiler complaining when returning char pointer array

I'm trying to return an array of char pointers but compiler doesn't seem to like it.

char*[] get_multiple(int x) {
    char *tmp[x];
    int i;
    for (i=0;i<x;i++)
        tmp[i]=strdup("abc");
    return tmp;
}

The compiler errors out with the following:

error: expected identifier or '(' before '[' token 

on line 1

Any idea why the compiler doesn't like it and how to fix it?
(I know I can alternatively pass in a structure from the caller to store the return pointers, but I want to avoid doing that)

Upvotes: 1

Views: 117

Answers (3)

dreamlax
dreamlax

Reputation: 95315

There are two types that you can't use as return types of functions:

  1. Function types
  2. Array types

What you need to do is declare a function that returns a pointer to pointer to char, or char **. You must allocate enough memory to store the pointers to the strings — so, if you need 7 strings, you must allocate enough space to hold at least 7 char * objects — and then you must allocate space for each of the 7 strings and assign these to the char * you just allocated. Alternatively, if all of the strings in this array will have a maximum length, you can declare one contiguous block of memory and calculate the offset to each string.

To aid memory management, it might help to also create a free_multiple function.

char **get_multiple(size_t max)
{
    char **multiple = malloc(max * sizeof(*multiple));
    for (size_t i = 0; i < max; i++)
        multiple[i] = malloc(/* determine max length of string including null terminator */);
    return multiple;
}

void free_multiple(char **multiple, size_t max)
{
    for (size_t i = 0; i < max; i++)
        free(multiple[i]); /* free individual strings */
    free(multiple); /* free the container as well */
}

Upvotes: 1

nonsensickle
nonsensickle

Reputation: 4528

Allow me to add to @Lidong Guo's answer (quoted below)

You can't create a array by :char * tmp[x],since x is known runtime!

use char **tmp = malloc(x*sizeof(char *)); instead

By looking at your code, I can see that you have misunderstood either what the array label tmp actually represents or where tmp is actually located.

When you allocate a variable (or an array of static size) in a function, it is stored on the stack, in your current stack frame. This stack frame is destroyed/freed as soon as the function returns and you should NOT be using/referencing that memory any more!!!

tmp is a label that represents the memory address at which the tmp array is located. This is on the stack so when your function returns it is no longer a valid pointer!

Forgive me if you already know this but judging by your terminology I suspect you might not.

In C you CAN NOT assign arrays to other arrays!

int array1[10], array2[10];

// ... Put some values into array 1 ...

array2 = array1; // ILLEGAL! DOES NOT COPY AN ARRAY

Similarly, if you return tmp you are returning the address, NOT the array so if you are assigning it to another variable you should be copying it instead of assigning it!

Hence C does not allow you to return an array and you should be returning pointers instead.

But even when you return a pointer to tmp you will be in trouble because of the way you are trying to allocate it (on the stack) so @Lidong Guo suggested that you allocate it on the Heap where it can live even after your function returns. However, this means that you will need to remember to free that memory!

So a rewrite of your function using @Lidong Guo's code would look like

char** get_multiple(int x) {
    char **tmp = malloc(x * sizeof(char*));
    int i;
    for (i=0;i<x;i++)
        tmp[i]=strdup("abc");
    return tmp;
}

And a hypothetical main would use it like so:

int main()
{
    char** multiple7;

    multiple7 = get_multiple(7);

    // Do some stuff on multiple 7
    free(multiple7[3]);

    // Do some more stuff ...

    // Don't forget to free multiple7 array memory too
    free(multiple7);

    return 0;
}

Upvotes: 2

Lidong Guo
Lidong Guo

Reputation: 2857

You can't create a array by :char * tmp[x],since x is known runtime!

use char **tmp = malloc(x*sizeof(char *)); instead

Upvotes: 0

Related Questions