2016-04-04 3 views
-3

Рассмотрим следующий код:Почему нет недопустимого предупреждения для неподписанного типа?

unsigned int n = 0; 
unsigned int m = n - 1;    // no warning here? 
if (n > -1) { 
    std::cout << "n > -1.\n"; 
} else { 
    std::cout << "yes, 0 is not > -1.\n"; 
} 

Код выше выдает предупреждение о if состоянии if (m > -1) для сравнения подписанных и неподписанных целые выражения. У меня нет конкуренции. Меня беспокоят первые два оператора присваивания.

unsigned int n = 0; 
unsigned int m = n - 1; 

Мое мышление является то, что компилятор должен дать мне предупреждение о втором задании, потому что он знает, что переменная n не имеет знака со значением 0 от первой линии, и была предпринята попытка вычесть из нулевое значение и присвоение его неподписанному типу.

Если следующая строка после второго присваивания отличается от оператора if или чего-то подобного, то соответствующий код мог проскользнуть.

Да, есть преобразование сужения перед назначением m, и да, компилятор не жалуется на это, о чем также упоминал Маршалл Клоу в своем рассказе Lightning Talk от C++ Now 2017 (Fighting Compiler Warnings).

short s = 3 * 6; 
short s = integer * integer; 
short s = integer; 

Итак, почему компилятор не может рассказать мне о возможном недополнении этого кода?

Составители:

  • Clang 3.7/4.0 (-Wall -Wextra)
  • GCC 5.3/7.1.1 (-Wall -Wextra -pedantic)
  • Microsoft C/C++ 19.00.23506
+0

Какое предупреждение вы ожидаете получить? Предупреждение, которое вы получаете в выражении if, - это сравнение между подписанными и беззнаковыми целыми выражениями *, которое не является тем, что происходит в 'unsigned int m = n - 1;' – NathanOliver

+0

Вы пытались использовать опции '-Wall' и' -Wextra' GCC? – Plouff

+0

@Plouff: Да, я использовал -Wall -Wextra с GCC. –

ответ

1

Причина в том, что if (n > -1) никогда не может быть ложным, но unsigned int m = n - 1; - это фактическое юридическое выражение, которое вы, возможно, хотели написать. От 5/9 Есть куча правил о том, как получить ваши подписали неподписанные тип, чтобы иметь последовательный тип, и все из них не за исключением конечного состояния по умолчанию

В противном случае оба операнд должен быть преобразован в unsigned integer тип, соответствующий типу операнда со знаковым целым числом .

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

+0

Есть ли свободные статические проверки кода, которые выдавали бы предупреждения для подобных проблем? – Plouff

+0

«устаревший код»: он делает ** не ** должен быть устаревшим кодом, это совершенно правильная вещь для записи в новом коде. С другой стороны, использование неподписанного типа для чего-то другого, кроме типа bigint (где вы хотите использовать wraparound) или битового поля, обычно вводится в заблуждение. –

Смежные вопросы