Должен ли я отключить компилятор C предупреждение о несоответствии со знаком / без знака? - PullRequest
15 голосов
/ 05 февраля 2009

Компилятор Microsoft C предупреждает, когда вы пытаетесь сравнить две переменные, одна из которых подписана, а другая - без знака. Например:

int a;    
unsigned b;

if ( a < b ) { // warning C4018: '&lt;' : signed/unsigned mismatch

}

Было ли это предупреждение в мировой истории когда-либо улавливать настоящую ошибку? Во всяком случае, почему это там?

Ответы [ 11 ]

30 голосов
/ 05 февраля 2009

Никогда не игнорируйте предупреждения компилятора.

24 голосов
/ 05 февраля 2009

О, это так. Но наоборот. Игнорирование этого предупреждения однажды вызвало у меня сильную головную боль. Я писал функцию, которая построила график и смешала переменные со знаком и без знака. В одном месте я сравнил отрицательное число с неподписанным:

int32_t t; ...
uint32_t ut; ...

if(t < ut) { 
    ...
}

Угадай, что случилось? Номер со знаком получил повышение до типа без знака и, таким образом, в конце был больше , хотя первоначально он был ниже 0. Это заняло у меня пару часов, пока я не нашел ошибку.

4 голосов
/ 06 февраля 2009

Если вам нужно задать вопрос, вы недостаточно знаете, безопасно ли его отключить, поэтому ответ - нет.

Я бы не отключил его - я не думаю, что я всегда знаю лучше, чем компилятор (не в последнюю очередь потому, что я часто этого не знаю), а точнее потому, что я иногда допускаю ошибки из-за недосмотра, когда компилятор этого не делает

3 голосов
/ 05 февраля 2009

Вы должны изменить a и b, чтобы оба использовали подписанные типы или оба использовали неподписанные типы. Но это может быть непрактично (например, это может быть вне вашего контроля).

Предупреждение о том, что нужно ловить сравнения между целым числом со знаком с отрицательным значением и целым числом без знака - если величины обоих чисел малы, первое будет (неправильно) считаться большим, чем второе.

2 голосов
/ 05 февраля 2009

Предупреждения существуют с определенной целью ... Они заставляют вас задуматься о своем коде!

Лично я бы всегда явным образом приводил подписанные -> без знака и без знака -> подписанные, если это возможно. Делая это, вы гарантируете, что вы вступаете во владение транзакцией и знаете, что произойдет. Я понимаю, что это не всегда возможно, в зависимости от проекта, но всегда стремлюсь к 0 предупреждениям компилятора ... это может только помочь!

2 голосов
/ 05 февраля 2009

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

например. -1 равно 4294967295 при преобразовании из знака в без знака, теперь сравните это со значением 100 (без знака)

0 голосов
/ 02 ноября 2009

Я думаю, что лучше всего конвертировать число без знака в число со знаком (до сравнения). Скорее наоборот.

0 голосов
/ 07 февраля 2009

@ gimel Объяснение о том, как снимать всю ногу, найденную по вашей ссылке, действительно хорошо для этой проблемы.

- «Кто-то, кто избегает простых проблем, может просто пойти не так просто».

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

/ Johan

Обновление: правильный способ преобразования из uint в int - это проверка значения против limit.h или что-то в этом роде. (Но я редко делаю это сам, даже если я знаю, что должен ... :-)

0 голосов
/ 07 февраля 2009

Я даже настроил компилятор, чтобы сделать это предупреждение ошибкой компиляции. по причинам, которые все остальные парни уже упоминали.

Если я когда-либо сталкиваюсь с несоответствием со знаком / без знака, я спрашиваю себя, почему я выбрал другую "подписанность" Обычно это ошибка проектирования.

0 голосов
/ 07 февраля 2009

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

Если они вас раздражают, и вы принимаете / понимаете ситуацию, тогда установите каст и идите дальше.

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

...