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
.
1 Answer 1
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).
-
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?AJ_Smoothie– AJ_Smoothie2023年09月19日 16:26:19 +00:00Commented Sep 19, 2023 at 16:26 -
1I 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 withletter << 8
and add a comment.Edgar Bonet– Edgar Bonet2023年09月19日 17:10:56 +00:00Commented 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.2023年09月20日 03:30:35 +00:00Commented Sep 20, 2023 at 3:30 -
1I'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 intwoBytes
or potentially undefined behavior, depending on the value and system.timemage– timemage2023年09月20日 17:41:32 +00:00Commented 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.2023年09月20日 23:43:36 +00:00Commented Sep 20, 2023 at 23:43
int twoBytes = 0;
- the fact that you didn't implies that you expect letter to be treated as 16 bits.letter
to be in high byte oftwoBytes
, and I'm putting another char into the low byte oftwoBytes
. Even though the code I wrote worked, being the inquisitive person I am I realized it didn't make sense, hence the question.