Я столкнулся с ошибкой в моей программе:
for (int i = 0; i < objArray.size() - 1; ++i)
В моем случае objArray.size () — это длинная длинная без знака, а пустой вектор минус 1 равен примерно 18 квинтиллионам. Мне было интересно, должен ли цикл на каждой итерации приводить int к unsigned long long? Я проверил сборку и, используя int, создает код, отличный от size_t, без оптимизаций, с указанием -O2 он генерирует точно такую же сборку. Означает ли это, что это не неявное приведение?
Я не понимаю сборку, но сгенерированный код был:
test rcx, rcx
je .L32
add rdx, rax
а потом :
cmp rdx, rax
jne .L28
Это может быть вызвано оптимизацией компилятора. Стандарт c ++ говорит, что переполнение целочисленных типов со знаком не определено. В этом случае, i
начинается в 0
, Если предположить, что i
не записывается в цикл, таким образом, компилятор может сделать вывод, что i >= 0
, поскольку переполнение является неопределенным поведением и может быть сокращено.
Обычно для сравнения со знаком без знака значение со знаком должно быть преобразовано в тип без знака, следуя правилам, которые вы можете посмотреть здесь. Эти правила являются причиной предупреждений компилятора при сравнении типа со знаком и без знака (что приводит к путанице, например, -1 > 2U
правда). В этом случае это не имеет значения, хотя.
С предположением i >= 0
и подписанные типы с 2 дополнениями, компилятор может безопасно переосмыслить i
как unsigned long long
так как он знает, что знак-бит 0
, Вот что показывает ваш сборочный вывод.
Теперь мы можем видеть, что действительно есть ошибка. предполагать objArray.size() - 1
делает не вписаться в положительный знак int
, Это вызвало бы i
переполнение, вызывая неопределенное поведение, что всегда является плохой новостью.
Давайте рассмотрим код
для (int i = 0; i < objArray.size () — 1; ++ я)
вы делаете сравнение между int и size_t. Размер () -1 — это нижний знак без знака, когда массив пуст и приводит к значению std :: numeric_limits :: max (). Сравнение будет подписано / не подписано и использует правила продвижения типа, как указано здесь Подписанные / неподписанные сравнения