gcc has a useful flag -Wconversion
that produces a warning when there's an implicit conversion from a wider to a narrower type, potentially losing information. Unfortunately, it has the following ... unhelpful ... behaviour.
Consider this program:
int main(void) {
short x = 1;
x = x+x;
return 0;
}
Compiling this with -Wconversion produces
nonsense.c: In function 'main':
nonsense.c:3:8: warning: conversion to 'short int' from 'int' may alter its value [-Wconversion]
which is fair enough; on most platforms this will do something you might not expect if it happens that x==0x8000
. (The actual mechanism by which you get this warning: the operands to +
are subject to the "usual arithmetic conversions", which widens them to int; so the result is also of type int; then assigning back to x
is an implicit conversion from a wider to a narrower type.) But suppose you do expect and intend this behaviour. (You're simulating a 16-bit processor, or a 16-bit shift register; or you know the range of possible values of x
in this code and it'll never overflow.) You can tell the compiler by putting in an explicit cast:
int main(void) {
short x = 1;
x = (short)(x+x);
return 0;
}
and it then won't complain.
So far, so good. But if the assignment that's causing the trouble is a compound assignment -- +=
, *=
, <<=
, etc. -- then so far as I can see there is no way to get rid of this warning because there isn't any point in the code at which you could insert the explicit cast.
This means, for instance, that you can't have all of
int
.which seems sad.
So, the question: is there a good way to work around this? I can see the following ways:
#pragma GCC diagnostic ...
to disable the warning in bits of code that are known to provoke it despite not having bugs. (Downside: ugly, compiler-specific.)-Wconversion
. (Downside: This warning is useful elsewhere.)-Werror
; in any case it's good practice to make your code compile with no warnings at all, because the difference between "no warnings" and "some warnings" is easier to spot than the difference between "some warnings" and "some more warnings".)All of these seem unsatisfactory, and I'm wondering whether there's something cleverer that I'm missing.
(Note: of course I will accept a "no, that's it" answer if that's actually the truth.)
So, it looks as if the answer is that this really is the intended behaviour and there is no way to stop it that's much better than the ones listed above. (Mark B observed that you can write a function that does the same as +=
but with explicit casting. ecatmur proposed defining a new type with operator+=
functions to do the explicit casting.)
I'm accepting Mark B's answer; the actual answer to the question in the title is simply "yes" :-).
I assume that the logic for warning in this case is that it's functionally the same as the operation the compound operator implements. Compound operator syntax is supposed to do a very obvious compound operation and in this case you want to explicitly say you know exactly what you're doing. When you want to make it clear that intention exists, spelling out code more explicitly always wins: You're only writing it one time but a longer spelled out version will make it completely clear to future maintainers what your intention was.
I would suggest just de-compounding the operation and spelling out the cast. Your maintainers really won't mind and I doubt they'll think it's ugly.
Alternately, create a scalar_mult(short&, short)
function to hide away the cast. Then you show explicit intention and avoid the cast in every expression.
Finally you might be able to just avoid the shorter types entirely, avoiding the warning.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With