signed / unsigned char on zero

Hello, I recently bought a zero and started carrying over some of my sketches (previously have been using a Duemilanove) but have run into compatibility problems. After a while I’ve traced it down to the zero seemingly treating char as unsigned rather than unsigned.

I have run the following code on the two arduinos to test the treatment of char (and compared to byte):

void setup() {
  Serial.begin(9600);
}

void loop() {
byte b[7] = {-256,-255,-1, 0, 1, 255, 256};
char c[7] = {-256,-255,-1, 0, 1, 255, 256};
for (int i=0;i<7;i++){
  Serial.print("byte[");Serial.print(i);Serial.print("] : ");Serial.print((int)b[i]);Serial.print("      ");
  Serial.print("char[");Serial.print(i);Serial.print("] : ");Serial.println((int)c[i]);
}
delay(999999);
}

The results I get through the serial monitor are as follows:

Duemilanove:

byte[0] : 0 char[0] : 0
byte[1] : 1 char[1] : 1
byte[2] : 255 char[2] : -1
byte[3] : 0 char[3] : 0
byte[4] : 1 char[4] : 1
byte[5] : 255 char[5] : -1
byte[6] : 0 char[6] : 0

Zero:

byte[0] : 0 char[0] : 0
byte[1] : 1 char[1] : 1
byte[2] : 255 char[2] : 255
byte[3] : 0 char[3] : 0
byte[4] : 1 char[4] : 1
byte[5] : 255 char[5] : 255
byte[6] : 0 char[6] : 0

The Duemilanove results are as expected but the Zero is giving values of 255 where I would expect -1.

https://www.arduino.cc/en/Reference/Char seems to confirm that Char is signed on all boards.

Adding “signed” to the declaration does fix the Zero but I wouldn’t have expected this to be required. What am I missing?

How can you have an int8_ t with value -256?

A signed char has values from -128 to +127 An unsigned char has values from 0 to 255

David.

Thanks for your response David.

Perhaps I should have excluded some of those cases such as -256 which were just me making sure I understood what was going on.

It's the -1 case which has caused me trouble. Why is the Arduino Zero giving 255 in the output for that example (c[2]) given the convention that you mentioned?

-1 is 0b11111111111111111111111111111111   (32 bits)

If you are only using 8 bits, it is 0b11111111 (8 bits)

This is the fundamental difference between signed and unsigned.

David.

Thank you again for your response David.

Unfortunately I think I am missing something in what you are saying because I think I already understand the point you are making but it doesn’t appear to me to explain the difference in result between the two boards. Char should be signed and so I should get -1 in both cases.

Can you please confirm that you would expect the difference in output for the above sketch for the two boards?

Are you hinting perhaps that it’s a result of the Zero board being 32-bit rather than 8-bit?

I don’t suppose anyone else might be able to help?

Hi ultraproro,

the "C" language doesn't define if "char" is signed or unsigned, but this is platform dependent.

Remember that DUEMILANOVE is AVR based and ZERO is ARM based.

If you want portability of your code it is a bad habit to use "char" to do math. If you need math use "signed char" or "unsigned char", never "char". Use "char" only for printable characters.

As a patch for allow portability to code that doesn't follow this rules try to put this at the beginning of your code:

*#define char signed char *

Marco

Thanks Marco. I have suggested in the feedback forum that the char documentation is updated.

I submitted a pull request to fix the char documentation issue: https://github.com/arduino/reference-en/pull/527