Я получаю предупреждение с ключевым словом const
в C++ при использовании clang++ v. 17.0.1 или более поздней версии с флагом -Winteger-overflow
.
Вот фрагмент кода:
int foo_const()
{
const auto min = std::numeric_limits<int>::min(); // const keyword
return - min; // warning: overflow in expression; result is -2147483648 with type 'int' [-Winteger-overflow]
}
int foo()
{
auto min = std::numeric_limits<int>::min(); // no const keyword
return - min; // no warning
}
В функции foo_const
я получаю предупреждение о потенциальном целочисленном переполнении. Однако та же операция в неконстантной функции foo
компилируется без предупреждения.
Я был бы признателен за помощь в понимании того, почему ключевое слово const
вызывает предупреждение о переполнении в этом конкретном случае.
Без ключевого слова const
кажется, что оно допускает возможность переназначения min
более высокому значению, которое не переполняется при отрицании.
верно. Я поместил комментарий к предыдущей строке, потому что ключевое слово const вызывает такое поведение. Комментарии поменяю, спасибо.
«Я был бы признателен за помощь в понимании того, почему ключевое слово const вызывает предупреждение о переполнении в этом конкретном случае». -- Я думаю, было бы интереснее понять, почему в другом случае не срабатывает предупреждение о переполнении. Поскольку переполнение, очевидно, происходит в обоих случаях.
что говорит Джон: godbolt.org/z/YvaMPfhz1. В вопрос следует включить предупреждающее сообщение.
Интересно, что gcc ведет себя точно так же, предупреждая только в случае const.
Стандарт C++ не требует, чтобы компилятор обнаруживал этот UB. То, что компилятор выполняет такую проверку «ворса» и предупреждает о UB, является бонусом, даже если он делает это только в сценарии foo_const
. Дезинфицирующее средство UB улавливает UB в обоих режимах.
const int
обычно может быть повышен до constexpr int
, что позволяет провести дальнейшую проверку.
Когда вы используете квалификатор const
, компилятор автоматически заменит использование переменной исходным значением. Когда он пытается сделать это в выражении -min
, результатом является значение, выходящее за пределы диапазона int
.
В версии без const
ссылка на min
в операторе return
обрабатывается нормально, а не заменяется начальным значением. Таким образом, нет никакого известного переполнения.
Компилятор, возможно, мог бы обнаружить, что переменная не переназначается между инициализацией и использованием в операторе return
. Но, очевидно, он делает это не для обнаружения подобных ошибок (он может сделать это позже в оптимизаторе).
смотря какой компилятор. clang с радостью может ворчать в любом случае, но без дополнительных флагов для статического анализа он ставит под сомнение оператор return
, а не оператор присваивания. Логика, вероятно, основана на том факте, что это может быть код шаблона и, следовательно, не использоваться. В любом случае, предупреждение — это результат возможности встраивания, как вы написали.
Короткий ответ: компилятор просто недостаточно умен. Обе функции приводят к одному и тому же UB.
Я думаю, что переполнение происходит в следующей строке
return - min;