Часто объект, который я использую, будет иметь (подписанный) int
параметры (например, int iSize
) которые в конечном итоге хранят, насколько большим должно быть что-то. В то же время я часто буду инициализировать их -1
чтобы показать, что объект (и т. д.) не был настроен / не был заполнен / не готов к использованию.
Я часто заканчиваю с предупреждением comparison between signed and unsigned integer
когда я делаю что-то вроде if( iSize >= someVector.size() ) { ... }
,
Таким образом, я номинально не хочу использовать unsigned int
, Есть ли ситуации, когда это приведет к ошибке или неожиданному поведению?
Если нет: как лучше всего справиться с этим? Если я использую флаг компилятора -Wno-sign-compare
Я мог (гипотетически) пропустить ситуацию, в которой я должен использовать unsigned int
(или что-то типа того). Так что я должен просто использовать приведение при сравнении с unsigned int
—например. if( iSize >= (int)someVector.size() ) { ... }
?
Да, есть и очень тонкие. Если вам интересно, вы можете проверить эта интересная презентация Стефан Т. Лававей об арифметическом преобразовании и ошибке в реализации Microsoft STL, которая была вызвана только при сравнении со знаком и без знака.
В общем, проблема связана с тем фактом, что из-за арифметики дополнения 2 очень маленькое отрицательное целочисленное значение имеет такое же битовое представление, что и очень большое целое число без знака (например, -1 = 0xFFFF = 65535
).
В конкретном случае проверки size()
почему бы не использовать тип size_t
за iSize
на первом месте? Беззнаковые значения просто придают вам большую выразительность, используйте его.
И если вы не хотите объявлять iSize
как size_t
Просто дайте понять с помощью явного приведения, что вы знаете природу этого сравнения. Компилятор пытается оказать вам услугу с этими предупреждениями, и, как вы правильно написали, могут быть ситуации, когда их игнорирование может вызвать очень сильную головную боль.
Таким образом, если iSize
иногда отрицателен (и должен оцениваться как менее чем все unsigned int
значения size()
), используйте идиому: if ((iSize < 0) || ((unsigned)iSize < somevector.size())) ...
Других решений пока нет …