13

I am trying to create a new integer array which is derived from a string of characters. For example :

char x[] = "12334 23845 32084";  

int y[] = { 12334, 23845, 32084 };

I am having trouble understanding how to return an array ( which I understand isn't possible ) from a function.

I originally tried :

/* Convert string of integers into int array. */
int * splitString( char string[], int n )
{
    int newArray[n];

    // CODE

    return ( newArray );
}

int main( void )
{
    int x[n] = splitString( string, n );

    return ( 0 );
}

I later learned that you can not do this.

How do pointers work in regards to functions?

Thank you.

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
Garee
  • 1,274
  • 1
  • 11
  • 15

7 Answers7

23

Typically, you require the caller to pass in the result array.

void splitString( const char string[], int result[], int n) {
    //....
}

This is advantageous because the caller can allocate that memory wherever they want.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 1
    This is the preferred method. In 99% of the cases it doesn't make sense to return any type of pointer from a function. – Lundin Mar 21 '11 at 14:40
  • 5
    Right. As mentioned in other answers, you could use `malloc(n*sizeof(int))` in you function to allocate the memory and return that pointer, but then you always have to remember to eventually `free` the memory as well. Since the `malloc` is hidden in a function at a different level of abstraction, you're prone to forget. So it's best to allocate the memory and pass the pointer in to the function, use the result, and then free the memory so you can easily match up your `malloc`s with your `free`s. – JCooper Mar 21 '11 at 14:56
  • @JCooper: The caller can also allocate that memory from a pool, off the stack, or wherever else he wants to put it, but the function cannot. – Puppy Mar 21 '11 at 15:24
  • 1
    your syntax is not correct. The `[]` come after the name of the parameter. – Jens Gustedt Mar 21 '11 at 16:35
15

The problem is you're returning a pointer to something on the stack. You need to create your array on the heap, then free it when you're done:

int * splitString( char string[], int n )
{
    int *newArray = malloc(sizeof(int) * n);

    // CODE

    return ( newArray );
}

int main( void )
{
    int *x = splitString( string, n );

    // use it

    free(x);

    return ( 0 );
}
Brian Roach
  • 76,169
  • 12
  • 136
  • 161
7
int * splitString( char string[], int n )
{
    int newArray[n];
    return ( newArray );
}

This is very bad! The array newArray local to the function gets destroyed when the function returns. You'd be left out with a dangling pointer and using it would invoke undefined behaviour.

You can't return an array from a function. The best you can do is

int * splitString( char string[], int n )
{
    int *newArray = malloc(n*sizeof(int)); // the array gets allocated on the heap rather than on the stack(1)
    // Code 
    return ( newArray );
}

Don't forget to free the allocated memory.

(1) Note that the standard doesn't use/define the term stack or heap as such.

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • Yes I realise that now. I have scoured the web for some examples on how to implement correctly however I can not find anything. – Garee Mar 21 '11 at 14:14
  • @prasoonSaurav , so you have mentioned , newArray local to the function gets destroyed so we return pointer. Pointer usually stores address of the memory, then if we return pointer that contains address of the memory we created within the function, then that memory will also be destroyed Right? Could you please explain me, I couldn't find the answer – Sujananth Feb 25 '18 at 19:03
3

Rather than returning an array with return (newArray), you return a pointer to the first element of newArray.

The problem is that you're allocating the array the wrong way. If you instantiate it with int newArray[n], memory gets allocated on the current stack frame. That memory will be freed as soon as your function returns, and whatever was in the array will be garbage. Instead, do the following:

int *newArray = malloc(n * sizeof(int));
// etc.
return newArray

By using malloc, you allocate memory on the heap, where it will survive past the end of the current stack frame. Just remember to free(newArray) somewhere in your program when you're done.

Jacob
  • 1,516
  • 9
  • 7
2

You can wrap an array in a structure and then return an instance of the structure. I'm mentioning this for completeness, it's not really something you'd want to do as it's ugly and there are better alternatives.

#include <stdio.h>

struct retval
{
    int a[10];
};

struct retval test()
{
    struct retval v = {{1, 5, 6}};
    return v;
}

int main()
{
    struct retval data = test();
    printf("%d %d\n", data.a[1], data.a[2]);
}
jcoder
  • 29,554
  • 19
  • 87
  • 130
  • Just wondering, how does this work? isn't "v.a" a pointer to a location on the stack of "test"? Does "struct retval data = test();" result in a deep copy of the array? – Pradyumna Jun 12 '15 at 08:18
2

The main issue i see is trying to return memory which you allocated on the stack, which becomes invalid once the function it was allocated in reutrns (in this case your splitString). What you can do is allocate the memory in the caller, and pass a pointer to the beginning of the array into the function

/* Convert string of integers into int array. */
void splitString(char string[], int *out_arr, int n )
{

    // code that fills each cell of out_arr

}

int main( void )
{
    int x[n];
    splitString( string,(int *)x, n );

    return ( 0 );
}
TanyaV
  • 131
  • 1
  • 7
0

Of course it's possible. This is the way I prefer: int func(int** results)

Function returns number of elements in results. results is a pointer to an int array.

Dr McKay
  • 2,548
  • 2
  • 21
  • 26