0

I know I'm missing something so simple here, but I can't figure it out.

If I do char letter = 'A'; then letter = letter << 8, letter = 0, as one should expect, since we are shifting the bits "off the shelf" to the left.

But, if we do this:

char letter = 'A';

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

  int twoBytes = letter << 8;
  Serial.println(twoBytes, BIN);

}

void loop() {}

The result is 100000100000000, but why? << has precedence over =, so it should be bitshifting letter left by 8 first, then assigning that value (which should be 0) to twoBytes.

3
  • Isn't there an implication that it will work (for some definition of "work")? If you were expecting zero why not just write: int twoBytes = 0; - the fact that you didn't implies that you expect letter to be treated as 16 bits.
    – Nick Gammon
    Sep 20 at 6:05
  • I just want to point out that although you posted it here, this is entirely a C++ question. The Arduino compiler is the GNU C++ compiler. Nothing "Arduino" about the way it treats code you write, with the exception of some pre-processing that the IDE does. See here for more details about that.
    – Nick Gammon
    Sep 20 at 6:11
  • 1
    @NickGammon .....because I need letter to be in high byte of twoBytes, and I'm putting another char into the low byte of twoBytes. Even though the code I wrote worked, being the inquisitive person I am I realized it didn't make sense, hence the question. Sep 20 at 15:00

1 Answer 1

4

This is a funny, non-intuitive rule of the C++ language called “integral promotion”. Simply stated, it says that no computation is ever performed on a type smaller than int: anything smaller gets implicitly promoted to int as soon as it appears in an arithmetic or logic expression.

See Implicit conversions in cppreference.com (warnings: it's hairy).

5
  • Thank you, I'll take it on faith! Would it be good practice to say int twoBytes = letter; twoBytes << 8; instead for clarity, or does it even matter? Sep 19 at 16:26
  • 1
    I would say that, for an experienced C or C++ programmer, it may not really matter. For someone unfamiliar with these rules, anything that can make the code clearer is a good thing. You may also write int twoBytes = int(letter) << 8;, or you may stick with letter << 8 and add a comment. Sep 19 at 17:10
  • In this sort of case, where you only want the right-most 8 bits I would personally "and" it, like this: int twoBytes = (letter << 8) & 0xFF; Since you want the low-order byte, make it explicit.
    – Nick Gammon
    Sep 20 at 3:30
  • 1
    I'm not sure how what you're saying is connected to what they're saying, but int twoBytes = (letter << 8) & 0xFF; is either complicated way of putting zero in twoBytes or potentially undefined behavior, depending on the value and system.
    – timemage
    Sep 20 at 17:41
  • The OP was surprised that the result wasn't zero, so I was pointing out that if you are doing a shift (left or right) and you aren't sure how many bits are being retained in the result, then anding it would make it clear. I don't see how the results could possibly be undefined.
    – Nick Gammon
    Sep 20 at 23:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.