Unsigned chars: Subtracting from zero and adding to 255

6 posts / 0 new
Author
Message

Hi folks,

I'm seeing some peculiar performance in one of my functions. Is the following true:

```unsigned char i=0;
i-1 will equal 255

unsigned char j=255;
j+1 will equal 0```

It seems like I'm not getting those results with this formula:

```//Stores current x_loc & y_loc to array
void BOX_store_loc(void)
{
//Step through each of 4 columns
for (unsigned char i=0; i<4; i++)
{
if ((x_loc+i >= BOX_board_left) && (x_loc+i <= BOX_board_right))
{
for (unsigned char j=0; j<4; j++) //Step through each of 4 rows
{
//prevent invalid indicies from being written
if (((y_loc-j) >= BOX_board_top) && ((y_loc-j) <= BOX_board_bottom))
{
if (BOX_piece[i/2] & 1<<((4*(i%2))+(3-j)))
{
BOX_location[x_loc+i] |= 1<<(y_loc-j);
}
}
}
}
}
}```

I have these declared these variables earlier in the code:

```#define BOX_board_top		0
#define BOX_board_bottom	7
#define BOX_board_left		0
#define BOX_board_right		11

unsigned char x_loc, y_loc;
unsigned char BOX_location[12] = {...```

I am having the problem when x_loc has been zero and then had 1 subtracted from it, then the BOX_store_loc() function is run.

Any help is greatly appreciated. Thanks!

edit: added the #define lines for reference

```unsigned char i=0;
i-1 will equal 255

unsigned char j=255;
j+1 will equal 0
```

Yes. This is all true.

Now that you have noticed these "features" of unsigned arithmetic, you must be aware that certain operations are suspect:

```a - b    // if a < b you would get a -ve result
a + b    // if a + b exceeds 255 you "rollover"
```
```a < b    // should always be logical
a - b < c // runs into the first problem ```

In common with all programming it is always worth hand-tracing with some extreme values. You quite often know that j is between 0 and 4 but other calculations can cause problems.

If all this seems hard work, just use regular signed ints everywhere. It may not be the most efficient but a HLL (high level language) is supposed to reduce this sort of brain-ache.

David.

`x_loc+i >= BOX_board_left`

This check is unnecessary. Since BOX_board_left is 0 and x_loc and i are unsigned, the statement is always true.

If what you are expecting is that when x_loc is 255 and i is one, that x_loc + i would be 0. But I think that you will find that when this is done, the variables are expanded to integers for the comparison. So the value will be 256, not 0. Try:

`(unsigned char)(x_loc + i)`

Regards,
Steve A.

The Board helps those that help themselves.

Dunno. But I can offer some simplifying suggestions.

Using unsigned variables as your indices means never having to say you're sor... wait; no... It means never having to check to see if they're ">= 0", because unsigned values are ALWAYS either greater than or equal to zero. So you can remove your #defines for BOX_board_left and _top.

Then replace your program's first comment with something that actually describes what the program is supposed to do. I can't see how the code you've written could be described by the first comment, since nowhere do you store either x_loc or y_loc to any array.

It might help if you split up the expression,

`1<<((4*(i%2))+(3-j))`

into some named intermediate steps so that a) readers would have more of an inkling of your intent, and b) you'll have variables you can ask the simulator or debugger about while you're trying to discover the difference between what you WANT the program to do and what you TOLD it to do.

And it might be nice if there were a description of what the mystery array BOX_piece is.

Thank you all.

Koshchi wrote:
...the variables are expanded to integers for the comparison. So the value will be 256, not 0. Try:

`(unsigned char)(x_loc + i)`

Indeed, thank you! It's funny because I tried this very early on:

`(unsigned char)(x_loc)+1`

But without including the +1 in the parenthesis I'm repeating the exact same issue!

Levenkay wrote:
b) you'll have variables you can ask the simulator or debugger about while you're trying to discover the difference between what you WANT the program to do and what you TOLD it to do.

I use linux exclusively (currently Ubuntu 8.10). This means I cannot us AVRStudio and I have never been successful in getting a simulator or a debugger working. If someone can point me to a method that works I'd love to hear it.

As for your remarks about comments and readability, you are entirely correct. I'm cobbling this together and am in desperate need of cleaning up my code. Many of my comments haven't change since major revisions to code were made.