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.

Juraj
18.3k4 gold badges31 silver badges49 bronze badges
asked Sep 19, 2023 at 15:36
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. Commented Sep 20, 2023 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. Commented Sep 20, 2023 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. Commented Sep 20, 2023 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).

answered Sep 19, 2023 at 15:58
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? Commented Sep 19, 2023 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. Commented Sep 19, 2023 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. Commented Sep 20, 2023 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. Commented Sep 20, 2023 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. Commented Sep 20, 2023 at 23:43

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.