Shifting char[]'s around

New to XMOS and XCore? Get started here.
JohnRobert
Active Member
Posts: 34
Joined: Fri Nov 02, 2012 8:10 am

Shifting char[]'s around

Post by JohnRobert »

G'day,

I've got this code:

Code: Select all

char rxString(in port RXD){
	char buffer[1024];
	int cnt = 0;
	while (1){
		char data = rxByte(RXD);
		if(data==13){
			break;
		} else {
			buffer[cnt] = data;
			cnt++;
		}
	}
        return buffer;
}
Where basically it reads all the bytes coming in over serial, dumps them into the char buffer[] until it gets CR (dec 13). The issue being, I'm not sure what to put as the function's return type... char[]? Or is this not possible. If it's not possible, would I have to do something like this:

Code: Select all

char rxString(in port RXD, char *buffer[]){
	int cnt = 0;
	while (1){
		char data = rxByte(RXD);
		if(data==13){
			break;
		} else {
			buffer[cnt] = data;
			cnt++;
		}
	}
}
I'm quite new to pointers, C syntax, and the such, but what I was thinking of with the above code, is you pass the address of a constructed char[], this function fills it up, and after executing it the char[] will be full of the recieved string. Is this correct? (Note, all above code DOES NOT work, it is just speculations).

Thanks

-John


User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

JohnRobert wrote:Or is this not possible.
It is not. Your array "buffer" is a local variable of your function,
that is, an "automatic variable" in C parlance; when you leave the
function the variable no longer exists (it typically is allocated on
the stack, and its space will be automatically reused).

There are two typical ways to handle your problem:
1) Pass an array to the function; it is then the caller's responsibility
to allocate it;
2) statically allocate it, either outside of your function or inside it.
It will then always take up space (which is not as bad as it sounds:
you need that space _anyway_, and you cannot usually timeshare it
with something else). There also then always is exactly one such
array, not one per function call, so you have to read its contents
and do what you want with it before calling the function again, since
it will overwrite it.

Code: Select all

char rxString(in port RXD, char *buffer[]){
That should be

Code: Select all

char buffer[]
I'm quite new to pointers, C syntax,
This isn't C, this is XC. An important difference is that you can
return an array, too! (In C, an array is sort-of the same as a pointer;
in XC, an array also "knows" its own length).
[...] Is this correct?
Yes, pretty much. Your use of "constructed" however suggests that
you want to allocate the space from some "heap" of memory. You do
not want to do that; memory is a finite resource, you want to more
carefully manage it, or else you will get out-of-memory problems
at runtime. Just allocate it statically :-)

Hope this helps,


Segher
JohnRobert
Active Member
Posts: 34
Joined: Fri Nov 02, 2012 8:10 am

Post by JohnRobert »

G'day,

I'm testing this now, but I'm getting another issue, which as been bugging me for quite some time,

Code: Select all

int main (){
	while(1){
		char message[128];
		getResult(RXD, message);
		int i = 0;
		while (1){
			if(message[i]==0){break;}
			txByte(CMP, message[i]);
			i++;
		}
		//sendCommand(TXD, "M0");
	}
	return 0;
}
At the line "int i = 0;", I get the error "parse error before 'int'". When I comment out the previous line, I don't get the issue - why?
User avatar
Bianco
XCore Expert
Posts: 754
Joined: Thu Dec 10, 2009 6:56 pm

Post by Bianco »

Move int i = 0; to before getResult().
You need to declare all variables at the start of a code block.
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

Hi John

It is also a good idea to do a bounds check on the receive buffer to make sure you do not write beyond the end of the array which will have unpredictable effects (even if you don't think the line will be bigger than it). This can be done by using a defined limit or some such

Code: Select all

define RXBUFSIZE 1024
....
char rxbuffer[RXBUFSIZE]
....
char rxString(in port RXD, char *buffer[]){
   int cnt = 0;
   while (cnt < RXBUFSIZE){
      char data = rxByte(RXD);
      if(data==13){
         break;
      } else {
         buffer[cnt] = data;
         cnt++;
      }
   }
}

Use this when you create and use the array, it also provides a central place to manage your buffer size rather than deep in the code, put it it something like config.h (along with other parameters) and include it where code requires it.

regards
Al
JohnRobert
Active Member
Posts: 34
Joined: Fri Nov 02, 2012 8:10 am

Post by JohnRobert »

G'day,

Thanks, all of this taken on board! Really loving developing with the XMOS, everything is working now.

Thanks Guys,

John
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

Folknology wrote:It is also a good idea to do a bounds check on the receive buffer to make sure you do not write beyond the end of the array which will have unpredictable effects
It is certainly a good idea to handle overflows graciously, if possible; but
array overflows do not have unpredictable effects in XC, instead they throw
an exception, stopping your thread (and probably taking the whole system
down with it).

Hey, at least it is easier to debug :-)
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

segher wrote:
Folknology wrote:It is also a good idea to do a bounds check on the receive buffer to make sure you do not write beyond the end of the array which will have unpredictable effects
It is certainly a good idea to handle overflows graciously, if possible; but
array overflows do not have unpredictable effects in XC, instead they throw
an exception, stopping your thread (and probably taking the whole system
down with it).

Hey, at least it is easier to debug :-)
I stand corrected and I learnt something new about XC, thanks Segher.

regards
Al