简体   繁体   中英

Why does bit-wise negate operator “~” cast to int? (conversion to ‘unsigned char’ from ‘int’ may alter its value)

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.

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.

all operands in expressions are promoted to at least int s, 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM