Reputation: 12506
How would you remove the warning produced by gcc -Wconversion
on the following code, without an explicit (=ugly) cast:
int main()
{
int val;
unsigned char c1 = (val % 65536) / 256;
unsigned char c2 = (val % 65536) % 256;
}
Is there a way to tell the compiler that obviously the cast is implicitely done during (% 65536) / 256
or % 256
For reference
$ gcc -Wconversion w.c
w.c: In function ‘main’:
w.c:4:36: warning: conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]
w.c:5:36: warning: conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]
Upvotes: 4
Views: 14820
Reputation: 11791
The warning is telling you that what you are doing isn't defined in all cases. If val
is negative, the ´%´ might return a negative result and asigning that to an unsigned char
is undefined. See also this question.
Either make sure val
is never negative and live with the warning (checking each time this hasn't changed!), or declare it unsigned int
.
Upvotes: 0
Reputation: 2816
Sounds like you want these results :
c1 = (val >> 8) & 0xff;
c2 = val & 0xff;
Edit :
From gcc wiki : Wconversion
Warn for implicit conversions that may alter a value. This includes conversions between real and integer, like abs (x) when x is double; conversions between signed and unsigned, like unsigned ui = -1; and conversions to smaller types, like sqrtf (M_PI). Do not warn for explicit casts like abs ((int) x) and ui = (unsigned) -1, or if the value is not changed by the conversion like in abs (2.0). Warnings about conversions between signed and unsigned integers can be disabled by using -Wno-sign-conversion. For C++, also warn for conversions between NULL and non-pointer types; confusing overload resolution for user-defined conversions; and conversions that will never use a type conversion operator: conversions to void, the same type, a base class or a reference to them. Warnings about conversions between signed and unsigned integers are disabled by default in C++ unless -Wsign-conversion is explicitly enabled.
The warning won't happen if val is unsigned
but you have to be sure about what you want to get for negative values.
Upvotes: 4
Reputation: 7065
Using a static cast (or casting your result TO an unsigned char)
int main()
{
int val;
unsigned char c1 = (unsigned char)((val % 65536) / 256);
unsigned char c2 = (unsigned char)(val % 256);
}
This will cut the warning, as it essentially tells the compiler, "Wait, I meant to do that".
If you are intending to not truly use signed VALUES, than you should start by:
unsigned int val;
instead of:
int val;
Even doing this, you will need the cast from unsigned int to unsigned char, because the compiler will ultimately still think that you didn't mean to down-convert the way that you did.
Upvotes: 6
Reputation: 2299
that's because int is signed and char is not, and this can lead confusion if int is a negative value because of two's complement. just add U near your literal and add unsigned to int and you will also fix your code, as actually val goes from -32768 to 32767 (signed) and not from 0 to 65536 (unsigned)
Upvotes: 0