0

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);
}
6
  • Can you use standard library functions? (You don't list any includes, and your own definition of getch suggests you cannot.) Commented Feb 14, 2016 at 13:52
  • You would have to declare your function as returning a pointer to char* and also create the array as a pointer to char and allocate it dynamically using malloc or else the data would be deleted when the function exits. I haven't programmed in C for a while so I could be off here. Commented Feb 14, 2016 at 13:53
  • Any reason you use a correct prototype-style declarator for main and getch, but not for getdata, whre you instead have a deprecated old-style one? Commented Feb 14, 2016 at 14:44
  • @Olaf corrected that mistake. Commented Feb 14, 2016 at 15:20
  • No, you did not! Before editing your code, you should first understand a problem. Commented Feb 14, 2016 at 15:25

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks what does the line if ( (recChars = malloc(6) == NULL ) return NULL; do? Also what would my main() look like? int main(void) { char *pointer = getdata(); uart_write(UART_D, (uint8_t *)recChars, sizeof(recChars)); free(pointer); return 0;}
He checks for the return value of malloc if this is NULL and you did not pass 0 as parameter, you probably have an ENOMEM error. Also you can't call sizeof in main since it returns the size of the pointer, not the number of elements in the array. If the array is '\0' terminated you should use strlen. If it's not '\0' terminated you could terminate it with '\0' yourself.
1

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

Comments

0

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; }

4 Comments

char * is not a pointer to an array! And a static array has other problems you don't even mention.
Sorry, I don't see where I claim that char * is "a pointer to an array".
Sorry, I seem to have interpreted too much into the text. However, the second sentence stands. Also, C does not require using a stack, so any reference at that level is irrelevant. YOu should have just stated clear what the standard says: accesses past the life-time is UB. And you mean define, not just declare.
I see what you mean and follow your path. You're right, I went somehow too far in this reply. Thanks for this clarification.
0

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.

3 Comments

thanks this what I wanted to do. Is it ok to call uart_write() in main()?
Also, why is this line necessary? What does it do? Thanks *(ptr_recChars + ndx) = retchar; //Asign the value to the array address + offset
Also, I should the & operator in getdata(&recChars); ? thanks

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.