Harmless Warning?

I have a kernel:
global void cmp(const uint8_t* restrict A, const uint8_t restrict rndnr){ …

During compilation, at this line:

uint8_t tmp[8] = {0, 0, 0, 0, (A[0] + A[1] + rndnr), rndnr, A[1], A[0]};

I get: "warning: invalid narrowing conversion from “int” to “unsigned char”.

It completes and runs without apparent error, but I don’t understand the “int” reference, as all elements of the calculation that causes the warning, (A[0] + A[1] + rndnr), are uint8_t.

By standard C++ semantics, in an expression any integer data of a type smaller (narrower) than int is first widened to int before operations are applied. Therefore the “result type” of the expression (A[0] + A[1] + rndnr) is int.

Try static_cast<uint8_t>(A[0] + A[1] + rndnr) once you have determined that this is safe (the sum of three uint8_t variables may well overflow the maximum representational range of uint8_t.

Thanks Norbert, overflow won’t be an issue here.

Interestingly, the exact same calculation in a slightly different form, in another kernel raises no warning:

uint8_t ch = A[0] + A[1] + rndnr;

I have never encountered this specific warning before. It’s possible that it is applied just to initializations. I find the wording odd, in that the word “invalid” is used. Off the top of my head I am not aware that the original code causes undefined behavior (instead of just potentially undesirable behavior) which is what I imagine when I read “invalid”, but maybe a close reading of the C++ standard indicates otherwise?

For self-documentation purposes, it is usually best to apply explicit type casts where narrowing conversions occur. That is an indication to the compiler and future code readers that the programmer was aware of the narrowing and (hopefully) considered the ramifications of that.

C++ is a whole new world for me, given my current status, swimming at the shallow end of C…

Does this semantic, (widening of narrow types), apply to C? Either way, explicit casting is the way to go.

It was inherited from C (C++ started out as “C with classes”). There may be some specific minor differences, but I wouldn’t know what they are. I have the C99 and C++11 standards as PDFs on the machine I am typing this on, but don’t feel like trudging through them for a side-by-side comparison …