Because I'm still figuring out 'Arduino C' I leave all warnings on.

Recently I got this one:

narrowing conversion of '(int)(((unsigned char)bx_0) | ((unsigned char)bx_1))' from 'int' to 'const byte... etc.

...referring to this line:

const byte pinMask[3] = {bx_0, bx_1, bx_0 | bx_1};

...pointing to the or symbol.

The code in question (much simplified to recreate this):

const int latch[2] = {2, 4};

const byte bx_0 = 1 << latch[0];
const byte bx_1 = 1 << latch[1];

const byte pinMask[3] = {bx_0, bx_1, bx_0 | bx_1};

(This happens whether I use byte, uint8_t, or unsigned char everywhere.)

Without the or operator, no warning. If bx_0 and bx_1 are simple bytes, not shifted into existence, no warning. If I do this:

const byte pinMask[3] = {bx_0, bx_1, (byte)(bx_0 | bx_1)};

...again, no warning.

However, I get no complaints about this:

const byte notMask = !(bx_1 | bx_0);

...so a further condition is that the problem or has to be in an initializer list. Yikes.

I don't get it. There's no way an or of two bytes can force widening, so where did the (int) cast come from? It apparently has something to do with the 1 << latch[0] code, but the result of that is still a byte, by definition.

I have a solution -- the (byte) cast -- but in the real code it's ugly and feels unnecessary. Everything is already just bytes.


That warning message arises when a compiler complies with C/C++ specifications.

According to ISO/IEC 9899:2011 part (“Bitwise inclusive OR operator”),

Each of the operands shall have integer type

Thus, in the evaluation of bx_0 | bx_1 within the statement const byte pinMask[3] = {bx_0, bx_1, bx_0 | bx_1};, the operands bx_0 and bx_1 are converted to int type before being OR'd together. This produces an int result, which then must be narrowed to byte before it can be stored in the byte array.

Knowing that the (byte) cast is necessary because of C/C++ specifications should convert your view of the cast from “ugly” and “unnecessary” to “necessary” and either “ok” or “oh well”. :)

  • Thanks, I suspected that might be the issue, except that all the conditions are necessary for the warning: complex definition, bitwise operator, initializer list. Remove any one and it doesn't warn. And OK, I'll accept 'necessary' (-: but I'm keeping "ugly" because in the actual code there are 16 elements to pinMask[], some with three or's.
    – Jim Mack
    Sep 10 '17 at 12:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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