print/println bug while passing in chars

I encountered some bizarre behavior when print-ing the result of a function that returns a char.

char readReg(char addr)
{
  char result;
  
  digitalWrite(pinCS, LOW);
  SPI.transfer(addr | 0x80);
  result = SPI.transfer(0x00);
  digitalWrite(pinCS, HIGH);
  
  return result;
}

void loop(){
...
  Serial.println(readReg(0x00), HEX); // println does NOT handle this very well!
}

prints out "FFFFFF55" which is not correct. I would have expected either "55" or "00000055".

In order to get the correct output, I have to add:

  Serial.println(0xff & readReg(0x00), HEX); // this works OK

just as a note, this does not work either:

 char a = readReg(0x00);
  Serial.println(a , HEX); // println does NOT handle this very well!

but this works fine:

  char a = 0x55;
  Serial.println(a , HEX); // works ok

but this does not:

  char a = 0xff & readReg(0x00);
  Serial.println(a , HEX); // total crap!

So weird!

I tried to reproduce but it worked all as expected (partly simulated) with Arduino 2009 && IDE 0021. A dive into the code of print() shows that the char is casted to a long before printing when using base HEX. For sources of print see C:\Program Files (x86)\arduino-0021\hardware\arduino\cores\arduino\print.cpp

3 questions:

  • which arduino are you using?
  • which ide version?
  • is this happening in a big program that maybe runnning out or RAM?

Rob

char is a SIGNED value. So anything above 127 will have the signbyte extended into the long. Just use byte b = c ; or similar and then you do not get the leadings FFs.

@Msquare
Very true, but the value appears to be 0x55 so sign extention should result in 0x00000055 and not 0xFFFFFF55, ...?

@ArduDano
Can you post your complete code?

I think Msquare already got the point, char is a signed 8bit integer. The value you are printing is probably 0xAB (which equals -0x55)
To clarify this issue, what is the output of

Serial.println((uint8_t) readReg(0x00), HEX);

If the output is AB then everything should become clear.

Udo