Предупреждение компилятора об унарной операции на unsigned int - PullRequest
6 голосов
/ 24 ноября 2010

У меня есть этот пример кода, который генерирует следующее предупреждение (компилятор VS2008 с SP1):

предупреждение C4146: унарный оператор минус применяется к типу без знака, результат все еще без знака

Код:

void f(int n)
{
}

int main()
{
    unsigned int n1 = 9;
    f(-n1);
}

Но поскольку функция f принимает свой параметр как int, не должен ли этот код компилироваться без каких-либо предупреждений?

Ответы [ 4 ]

15 голосов
/ 24 ноября 2010

, если x имеет тип unsigned int, то так же -x, и это фактически эквивалентно 2<sup>n</sup>-x (где n наиболее вероятно 32).Чтобы избежать появления предупреждений и , приведите к int:

f(-static_cast<int>(n));

Я бы рекомендовал прочитать главу «Выражения» стандарта C ++.Там вы увидите, что в выражении -x происходит интегральное продвижение на x, что означает, что почти все превращается в int, а unsigned int - нет.

Посмотрите на этот очень интересный пример:

template<class T>
void f(T x)
{
  //somehow print type info about x, e.g. cout << typeid(x).name() or something
}

int main()
{
  char x;
  f(x);
  f(+x);
  f(-x);
}

отпечатков:

char
int 
int

Но char -> int является интегральной рекламой, тогда как unsigned int -> int это преобразование

12 голосов
/ 24 ноября 2010

Стандарт 5.3.1 / 7

Операнд унарного оператора должен иметь арифметический или перечислимый тип, а результатом является отрицание его операнда.Интегральное продвижение выполняется для целочисленных или перечислимых операндов.Отрицательное значение беззнаковой величины вычисляется путем вычитания ее значения из 2n, где n - количество битов в повышенном операнде.Тип результата - это тип повышенного операнда.

И параграф по Integral Promotion 4.5 / 1

Значение типа char, подписанный char, без знакаchar, short int или unsigned short int могут быть преобразованы в значение типа int, если int может представлять все значения типа источника;в противном случае исходное значение r может быть преобразовано в значение типа unsigned int.

, т. е. целое число без знака не будет преобразовано в int.

2 голосов
/ 24 ноября 2010

Параметр передается по значению. В вызове функции f (-n1) оператор применяется перед передачей параметра в функцию. Отсюда и предупреждение.

0 голосов
/ 10 февраля 2011

Компилятор предупреждает вас, что применение унарного минуса к беззнаковому int является необычной вещью и может не дать ожидаемого результата. Результат, который вы получите в этом случае, будет эквивалентен вызову f (4294967287u), если вы используете 32-битный компилятор.

...