malat
malat

Reputation: 12506

conversion to ‘unsigned char’ from ‘int’ may alter its value

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

Answers (4)

vonbrand
vonbrand

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

Kiwi
Kiwi

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

trumpetlicks
trumpetlicks

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

Lesto
Lesto

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

Related Questions