Serial monitor converting to 32 bits?

I am at a loss to understand how this code produces the output in the serial monitor.

void setup() {
  // put your setup code here, to run once:
   Serial.begin(9600);
   print_i(0xFFFF);
   print_i(0x7FFF);
   print_i(-1);
   print_i(0x8000);
   print_i(0x80000000);
   print_i(0xFFFF8000);
}
void print_i(int i) {
   Serial.print(i,HEX);
   Serial.print("\t");
   Serial.println(i,BIN);
}
void loop() {
  // put your main code here, to run repeatedly: 

}

output in serial monitor:

FFFFFFFF	11111111111111111111111111111111
7FFF	111111111111111
FFFFFFFF	11111111111111111111111111111111
FFFF8000	11111111111111111000000000000000
0	0
FFFF8000	11111111111111111000000000000000
void print_i(int i) {
   Serial.print(i,HEX);
   Serial.print("\t");
   Serial.println(i,BIN);
}

This routine prints the integer in hexadecimal and binary notations. In both notations leading zeros are omitted, which is probably what is confusing you.

What part of the output was confusing?

I must confess I got a little confused in your test cases when you started passing in 32-bit test quantities to a 16-bit integer argument.

-br

Hi
Thanks for your replies. What is confusing me is that the 16-bit integer I send it is being converted to 32 bits. Why?
I put the attempt to 32 bit print in to show that I cannot use 32bit integers or pass them so why does serial monitor do it?

Mrs Z

I put the attempt to 32 bit print in to show that I cannot use 32bit integers or pass them

You can if the function expects 32 bit values. Yours does not.

void print_i(long i) {

…will do what you want.

-br

The implementation of print(int, int) in the Print class is as follows:

size_t Print::print(int n, int base)
{
  return print((long) n, base);
}

So 16 bit integers are converted to 32 bit integers before printing.

Thank you again.

I guess this means that I cannot stop it? I wanted to print a 16 bit integer.

Mrs Z

Zaplady:
Thank you again.

I guess this means that I cannot stop it? I wanted to print a 16 bit integer.

Mrs Z

Well, now that you know that the Print class will automagically cast to a long, combined with the observation that leading zeros are trimmed, try padding your ints with an MSint of zeros and send that resulting long to Print. (i.e. if you want to print 0xF3AD, pad it to get 0x0000F3AD and print that long.) Might work, might not.

Seems to me to be a bug in the Print class though because your experimentation shows that there is no way to predict what the new 16 bits will be that the Print class pads when it casts the input int as a long. Actually, the pattern seems to be the new 16 bits will be the same value as your MSbit, but without more statistics I can't say if that is actually happening, or coincidence... Thinking more about it, I wonder if it's because int is signed, and all those extra binary ones are appropriate for 'zero padding' a negative number... What happens if you try to pass an unsigned 0xFFFF to the Print class?

Seems to me to be a bug in the Print class though because your experimentation shows that there is no way to predict what the new 16 bits will be that the Print class pads when it casts the input int as a long.

No, this is not a bug, it's standard behavior. And you do print a 16 bit integer. My guess is you don't want to print a 16 bit integer but you want to print the 16 single bits of that integer. Am I right?

Try this slightly modified code:

void print_i(uint16_t i) {
   Serial.print(i,HEX);
   Serial.print("\t");
   Serial.println(i,BIN);
}

Thank you , this is exactly what I want. I did not realise that types not listed in the reference were available.
Thanks again
Mrs Z

pylon:

Seems to me to be a bug in the Print class though because your experimentation shows that there is no way to predict what the new 16 bits will be that the Print class pads when it casts the input int as a long.

No, this is not a bug, it's standard behavior.

Well, if you follow my train of thought through that paragraph, you see that I realized that the issue was int is a signed value. I probably should have put a strike-through on that sentence...