ultrasonic bananna
ultrasonic bananna

Reputation: 193

How to return pointer to array in c

I call the function getdata() below inside main(). getdata() reads in characters from the uart and puts them in an array. At the end of the function it writes out the array over uart.

My question is, how can I get this function to return the data? I understand that you cannot return arrays in c and that you should declare a function returning a pointer.

How could I do that with the function below so that I can write out the data in main instead of having to do it inside getdata().

int main(void)
{
    getdata();
}

void getdata(void)
{
    static uint8_t ndx;
    char recChars[6];
    char retchar;
    ndx = 0;

    retchar = getch(); 
    recChars[ndx] = retchar;
    ndx++;

    if (retchar == '\r'){
        recChars[ndx] = '\n';
        ndx = 0;
        uart_write(UART_D, (uint8_t *)recChars, sizeof(recChars));
    }            
}

char getch(void) {
uint8_t ch = 0;
chuart_read(UART_D, &ch);
return ((char) ch);
}

Upvotes: 0

Views: 5749

Answers (4)

Sourav Ghosh
Sourav Ghosh

Reputation: 134396

You need to make recChars a pointer and allocate dynamic memory to it using malloc() or family. Then, you can return the pointer to the caller and make use of it in the caller.

Something like

char * getdata()         //change return type
{
    static uint8_t ndx;
    char * recChars = NULL;  // change to pointer
    char retchar;
    ndx = 0;

    if ( (recChars = malloc(6)) == NULL ) return NULL;

    retchar = getch(); 
    recChars[ndx] = retchar;
    ndx++;

    if (retchar == '\r'){
        recChars[ndx] = '\n';
        ndx = 0;
        //uart_write(UART_D, (uint8_t *)recChars, sizeof(recChars));
    }     

  return recChars;      //finally return
}

Remember, the returned pointer needs to be free()-d in the caller, after the usage is over to avoid memory leak.

Upvotes: 2

Sorcrer
Sorcrer

Reputation: 1644

I would advice you to declare an array in the main() function itself pass the arrray as reference to getdata function, so whenever getdata() gets updated that will be reflected in the array in main().

Note: By the way why are you using sizeof(recChars), which will give 6, but you're only updating upto 2 location. I've incorporated this also in the code

int main(void)
{
    char recChars[6];
    int Rxd_Len = 0;

    Rxd_Len = getdata(&recChars); //Pass the address of array
    uart_write(UART_D, (uint8_t *)recChars, Rxd_Len );
}

int getdata(char *ptr_recChars)
{
    uint8_t ndx; // removed static since its not a required/mandatory
    char retchar;
    ndx = 0;

    retchar = getch(); 

    *(ptr_recChars + ndx) = retchar; //Asign the value to the array address + offset


    if (retchar == '\r'){
        ndx++;
        *(ptr_recChars + ndx) = '\n';

    }  

   return ndx;          
}

char getch(void) {
uint8_t ch = 0;
int ret;
ret = uart_read(UART_D, &ch);
return ((char) ch);
}

UPDATE:

Is it ok to call uart_write() in main() ? Yes you can do that, but since the uart_write() will be using the length to transfer you need to keep track of it using another variable.

Also, why is this line necessary? What does it do*(ptr_recChars + ndx) = retchar;? ptr_recChars is a pointer which points to the array recChars[6], so using this pointer we can update the array recChars[6] even though it is declared in main(), *(ptr_recChars + ndx) , here ndx is 0 so the first element of array is updated, then after that you increment ndx then, using the pointer variable we can point to the new updated location by *(ptr_recChars + ndx) (since ndx is new value now)

Also, I should the & operator in getdata(&recChars); No, the array name itself is a pointer so for recChars[6] simplay giving recChars alone will give the base address of the array, also note recChars and &recChars[0] means same. So if you give &recChars it means recChars is a address then adding &recChars assumes the address of a address which will give you an invalid value in your expression.

Upvotes: 0

user5922822
user5922822

Reputation: 209

You can write a function that returns a char * and use malloc to create some storage for this table, as mentioned above, or you can simply declare your array as static and return it. More explicitly:

char *getdata(void) { static char retChar[6]; ... return retChar; }

Works. The reason for this is that the array storage is reserved in a special segment.

A version with malloc reserves the storage for your array in the heap, which requires you to free it afterwards:

char *getdata(void) { char *retChar = (char *) malloc(6); ... return retChar; }

main() { char * ptr = getdata(); ... free(ptr); }

Finally the only thing you can't do is to declare the array and return it as is, with no static declaration and no malloc... The reason for this is that your array is allocated in the call-stack and so is potentially lost when you return from getdata. In other words, never ever do: char *getdata(void) { char retChar[6]; ... return retChar; }

Upvotes: 0

user5904801
user5904801

Reputation:

You have to write a function that returns a pointer to char and use malloc to allocate memory. You must use malloc because arrays declared like this

char v[11];

belong to the automatic storage class which means that they have block scope,they get deleted as soon as your function returns and they are not initialized by default. Dynamic memory instead can be accessed anywhere in your program if you have a pointer to that memory block. You have also remember to free the memory using free() to avoid memory leak. If you returned a pointer to an automatic array,you'd probably get a SIGSEGV because your pointer is holding a memory location that doesn't exist anymore. So you could write something like this:

char *foo(void)
{
    char *p = malloc(sizeof(type) * n);
    return p;
}

In main

int main(void)
{
    char *pointer = foo();
    /*Do something*/
    free(pointer);
    return EXIT_SUCCESS;
}

PS: I apologize for my english

Upvotes: 1

Related Questions