Arduino IDE and datatypes ... and valid datatypes ...

Hello,
the Arduino IDE makes me realy confused:

example:

  unsigned int ui = 32768;
  Serial.println(ui, BIN);
  
  int si = -32768;
  Serial.println(si, BIN);
  Serial.println(si, DEC);

a unsigned Integer ui = 32768 has a binary representation : 1000000000000000
all fine, it is a 2 Byte Integer
now a signed Integer si = -32768, and now a confusion, this has a binary representation : 11111111111111111000000000000000
in the end, the Serial.println(si,BIN) shows a 4 byte Integer ... so whats going on here ???

so now some thougts about the valid datatypes in the Arduino IDE:

many from c adapted code in the internet use a short datatyp in a Arduino Sketch. But the Ardiono Doc knows no short... so why can i compile code with a not valid datatype?

  short s = 16384;
  Serial.println(s, BIN);
  Serial.println(s, DEC);

100000000000000 = 15 bits, the 15. bit is also only 16384 ? ...
16384

now short s = -16384;

  short s = -16384;
  Serial.println(s, BIN);
  Serial.println(s, DEC);

11111111111111111100000000000000 : Wow, now we have a 4 byte "short"... whats going on here? is the serial.println implementation not correct?

my environment: win 7 64bit or Mac OSX Snow Leopard, Arduino IDE 22

Cheers

sbod

If you want to know the size of datatypes, you could try using the C compiler's intrinsic sizeof "function."

But the Ardiono Doc knows no short... so why can i compile code with a not valid datatype?

Well, that one is easy to answer. Undocumented is not equal to invalid.

This is a bug with the way the Arduino print class works. When printing the base, it converts all input datatypes into longs, does the conversion, then prints. However, when you convert a signed negative int to a signed negative long, it changes it's binary representation due to using a two's complement system for signed datatypes.

So the two's complement for -32768 in 16bit format is 1111111111111111
The two's complement for -32768 in 32 bit format is (as you've seen) 11111111111111110000000000000000

The Print library is causing this 32 bit output by converting the input data to long before performing the conversion. Positive values have the expected output for two reasons. The first, their binary representation is the same regardless the size of the datatype (assuming the type is large enough to hold the value), and second the Print library does not print leading zeros.

You have the native:
char :8 bits
unsigned char : 8bits
uint8_t :8bits
int8_t :8bits
int :16 bits
unsigned int :16 bits
uint16_t :16 bits
int16_t :16bits
uint32_t :32bits
int32_t : 32bits
long : 32 bits
unsigned long : 32bits
long long : 64 bits
uint64_t :64 bits
int64_t :64bits
unsigned long long : 64 bits
float : 32 bits
double : 32 bits

jraskell:
...
So the two's complement for -32768 in 16bit format is 1111111111111111
The two's complement for -32768 in 32 bit format is (as you've seen) 11111111111111110000000000000000
...

Close but no banana. (See Footnote.)

Binary representation of 32768 as a 16-bit unsigned integer is 1000000000000000 (A 1 and 15 zeros)
When the print function promotes it to an unsigned long integer, the MSB (0) is extended into the upper bits and the 32-bit unsigned integer is 00000000000000001000000000000000 (16 zeros, a 1, and 15 zeros)
The Serial.print stuff does not print leading zeros, so you get 1000000000000000

However...

Binary representation of -32768 as a 16-bit integer is also 1000000000000000 (A 1 and 15 zeros.)
When the print function promotes it to a long integer, the MSB (1) is extended into the upper bits and the representation as a 32-bit signed integer is 11111111111111111000000000000000 (17 ones and 15 zeros).

If you print the decimal value of the unsigned int you get 32768 and if you print the decimal value of the signed int you get -32768

Regards,

Dave

Footnote:

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

    unsigned int ui = 32768;
    Serial.print("ui = 0x"); Serial.println(ui, HEX);
    Serial.print("ui = 0b"); Serial.println(ui, BIN);
    Serial.print("ui = decimal ");Serial.println(ui);

    int si = -32768;
    Serial.print("si = 0x"); Serial.println(si, HEX);
    Serial.print("si = 0b"); Serial.println(si, BIN);
    Serial.print("si = decimal "); Serial.println(si);
    Serial.println();
}
void loop() {}

ui = 0x8000
ui = 0b1000000000000000
ui = decimal 32768
si = 0xFFFF8000
si = 0b11111111111111111000000000000000
si = decimal -32768

If you want to print the int values without worrying about "promotions" to longs, and you can live with hex instead of binary, you can use sprintf:

    char buffer[30];

    unsigned int ui = 32768;
    sprintf(buffer, "ui = 0x%04x", ui);
    Serial.println(buffer);
    sprintf(buffer, "ui = %u decimal", ui);
    Serial.println(buffer);
    
    int si = -32768;
    sprintf(buffer, "si = 0x%04x", ui);
    Serial.println(buffer);
    sprintf(buffer, "si = %d decimal", si);
    Serial.println(buffer);
    Serial.println();

Output:


ui = 0x8000
ui = 32768 decimal
si = 0x8000
si = -32768 decimal

davekw7x:
Binary representation of -32768 as a 16-bit integer is also 1000000000000000 (A 1 and 15 zeros.)
...
as a 32-bit signed integer is 11111111111111111000000000000000 (17 ones and 15 zeros).

That is correct. Thanks for the correction. I was mainly intent on explaining that it was a bug in the way the Print library handles the datatypes than providing an example, but the example should have been accurate nonetheless.

jraskell:
... it was a bug in the way the Print library handles...

It certainly can be confusing. If people want the values of the printed integer data types to be a little closer to reality, they can consider giving up the convenience of the Print stuff in favor of learning good old C sprintf. See the amended footnote of my previous post.

or itoa and the regular print.

Hi,

It certainly can be confusing. If people want the values of the printed integer data types to be a little closer to reality, they can consider giving up the convenience of the Print stuff in favor of learning good old C sprintf. See the amended footnote of my previous post.

for myself it costs me many hours, because i use this Serial print function for code debugging and im looked for the reason why my integer variables doesn´t shift correctly ... so i think the arduino ide needs a reliable debbuging view for the variables :cold_sweat:

valid datatypes:

Well, all the native c datatypes are valid.... so please Arduino Team, add this little important information to the datatype documentation :%

Cheers
sbod

so i think the arduino ide needs a reliable debbuging view for the variables

The IDE is basically an editor that can invoke a compiler/linker/uploader. The code that the compiler/linker/uploader produces and sends to the Arduino runs on another computer. How would having a debugger on the PC help?

There is not near enough memory/program space to add a debugger to the Arduino.

Good design and a thorough understanding of C++ is necessary to build applications that don't need to be debugged.