0
votes

GCC 4.9.1 reports "warning: conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]" with the following code

#include <cstdlib>

int main( int , char*[] ) {
  unsigned char *dest = new unsigned char[16];
  const unsigned char *src = new unsigned char[16];
  for( size_t i = 0; i != 16; ++i) {
    dest[i] = ~(src[i]);
  }
  return 0;
}

Obviously, both src and dest are both pointers to an array of unsigned char and I only want the latter to be the bit-wise negation of the former. For some strange reason the ~ operator seems to return an int and thus triggering the warning. Why? Is this intended behaviour?

Of course, I know I could use a static_cast<unsigned char>() to prevent the warning, but I feel that something else is wrong and the warning should not be there in the first place.

2

2 Answers

2
votes

I guess the literal answer is because the Standard says so. From [expr.unary.op]:

The operand of ~ shall have integral or unscoped enumeration type; the result is the one’s complement of its operand. Integral promotions are performed. The type of the result is the type of the promoted operand.

which, according to [conv.prom] is:

A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.

And int has higher rank than unsigned char. So yes, it's intended behavior, and an explicit static_cast squelches the warning.

0
votes

all operands in expressions are promoted to at least ints, because int should represent 'natural' integral type for given architecture.

So this warning is proper - type on right side of assignment will be int (for some people it might indicate place for optimization*), static_cast is a good solution (I would add mask for 0xFF to it, just to be sure and properly state my intent).

*) for example: one could negate 4 bytes at once, making better use of CPU. Some compilers might do it by them selfs.