简体   繁体   中英

Arduino code: shifting bits seems to change data type from int to long

on my Arduino, the following code produces output I don't understand:

void setup(){
  Serial.begin(9600);
  int a = 250;

  Serial.println(a, BIN);
  a = a << 8;
  Serial.println(a, BIN);
  a = a >> 8;
  Serial.println(a, BIN);


}

void loop(){}

The output is:

11111010
11111111111111111111101000000000
11111111111111111111111111111010

I do understand the first line: leading zeros are not printed to the serial terminal. However, after shifting the bits the data type of a seems to have changed from int to long (32 bits are printed). The expected behaviour is that bits are shifted to the left, and that bits which are shifted "out" of the 16 bits an int has are simply dropped. Shifting the bits back does not turn the "32bit" variable to "16bit" again.

Shifting by 7 or less positions does not show this effect.

I probably should say that I am not using the Arduino IDE, but the Makefile from https://github.com/sudar/Arduino-Makefile .

What is going on? I almost expect this to be "normal", but I don't get it. Or is it something in the printing routine which simply adds 16 "1"'s to the output?

Enno

The function printing numbers in Arduino is defined in /arduino-1.0.5/hardware/arduino/cores/arduino/Print.cpp

size_t Print::printNumber(unsigned long n, uint8_t base) {
  char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
  char *str = &buf[sizeof(buf) - 1];

  *str = '\0';

  // prevent crash if called with base == 1
  if (base < 2) base = 10;

  do {
    unsigned long m = n;
    n /= base;
    char c = m - base * n;
    *--str = c < 10 ? c + '0' : c + 'A' - 10;
  } while(n);

  return write(str);
}

All other functions rely on this one, so yes your int gets promoted to an unsigned long when you print it, not when you shift it.

However, the library is correct. By shifting left 8 positions, the negative bit in the integer number becomes '1', so when the integer value is promoted to unsigned long the runtime correctly pads it with 16 extra '1's instead of '0's.

If you are using such a value not as a number but to contain some flags, use unsigned int instead of int .


ETA: for completeness, I'll add further explanation for the second shifting operation.

Once you touch the 'negative bit' inside the int number, when you shift towards right the runtime pads the number with '1's in order to preserve its negative value. Shifting to the left k positions corresponds to dividing the number by 2^k , and since the number is negative to start with then the result must remain negative.

除了其他答案之外,整数可能以 16 位或 32 位存储,具体取决于您拥有的 arduino。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM