Целочисленное переполнение и умножение целых чисел в c ++

    int y ;
    y = 7000000000*1.0;

Это не дает ошибки в cpp

Хотя

    int y ;
    y = 7000000000;

Это приводит к целочисленному переполнению

Кто-нибудь может объяснить эти два сценария.


person Aneket    schedule 27.02.2020    source источник
comment
Результат 7000000000*1.0 - double. 7000000000 не подходит для int.   -  person DeiDei    schedule 28.02.2020
comment
Я видел несколько 64-битных int, которые могут содержать 7000000000, но они необычны.   -  person user4581301    schedule 28.02.2020
comment
Если мы будем придерживаться стандарта C ++ и нам не предоставили целевой компилятор или платформу, поэтому стандарт - это все, что нам нужно, в этих сценариях будет неопределенное поведение и не может быть объяснено. Примечание: g ++ 8.3 с -pedantic -Wall -Wextra -Wconversion выдает предупреждения для обоих.   -  person user4581301    schedule 28.02.2020
comment
@ user4581301: целочисленное преобразование определяется реализацией, а не неопределенным (проект C ++ 2017 n4659 7.8 3).   -  person Eric Postpischil    schedule 28.02.2020
comment
Что вы имеете в виду под cpp? Существует программа под названием cpp, но она просто предварительно обрабатывает код и не выдаёт ошибку. за то, что вы представили. Так может ты имеешь в виду C ++? Если так, то ошибку выдает не язык, а ваш компилятор. Поэтому вам может потребоваться указать, какой компилятор вы используете, и какие параметры компилятора вызывают ошибку для последнего, но не для первого.   -  person JaMiT    schedule 28.02.2020
comment
Мой компилятор генерирует предупреждение для первого кода, а во время выполнения выводит runtime error: 7e+09 is outside the range of representable values of type 'int' и устанавливает y равным 0.   -  person Eljay    schedule 28.02.2020


Ответы (1)


В вашей реализации C ++ и y = 7000000000*1.0, и y = 7000000000 приводят к переполнению того, что может быть представлено в int во время преобразования. Для преобразования из типа с плавающей запятой в целочисленный тип поведение в случае такого переполнения не определяется стандартом C ++. Для преобразования из одного целочисленного типа в другой он определяется реализацией.

Однако ваш компилятор диагностирует последнее во время компиляции и не может диагностировать первое. Это не означает, что первое в порядке (это не так), просто компилятор не сообщает о проблеме (и это не требуется стандартом C ++).

person Eric Postpischil    schedule 28.02.2020
comment
[conv.fpint] Prvalue типа с плавающей запятой можно преобразовать в prvalue целочисленного типа. Преобразование обрезается; то есть дробная часть отбрасывается. Поведение не определено, если усеченное значение не может быть представлено в типе назначения. -- Просто быть чистым :) - person eerorika; 28.02.2020
comment
@eerorika: Я не уверен, что вы поясняете. Это переполнение происходит только в том случае, если усеченное значение не подходит, а не какое-либо свойство исходного значения перед усечением? Что спецификация взята из определенной части стандарта? Что-то другое? - person Eric Postpischil; 28.02.2020
comment
Я поясняю, что поведение ... не определяется стандартной частью ответа C ++. Это немного расплывчато и не обязательно передает то же значение, что и неопределенное поведение. - person eerorika; 28.02.2020
comment
@eerorika: Это не расплывчато, и я намеренно использую эту формулировку, потому что она лучше. Люди используют «undefined» в стандартах C и C ++, как если бы это была вещь, особенно вещь, которую вы должны сделать, потому что поведение не определено. Но это ложное понимание того, что означает «неопределенный» в стандарте. Это буквально означает то, что я написал: это не определено стандартом. Это не вещь, это отсутствие вещи. Это похоже на город, который говорит: «Когда вы покидаете городскую черту, мы не гарантируем вам электричество, воду или полицию». Но тогда вы находитесь в другом месте, и вы можете найти другие… - person Eric Postpischil; 28.02.2020
comment
… Другие поставщики для ваших нужд. К сожалению, слишком многие люди трактуют «undefined» в стандартах C и C ++, как если бы они имели в виду «город запрещает это действие; если вы это сделаете, вы нарушите закон ». Это не относится к делу. Стандарты предназначены для реализации с целью предоставления расширений, а расширения обязательно необходимы для подавляющего большинства коммерчески полезных программ. Только чисто текстовые взаимодействия и чисто абстрактные вычисления могут выполняться в строго соответствующих C или C ++. Связывание с любой другой библиотекой требует использования «неопределенного» поведения, включая взаимодействие с графическим интерфейсом пользователя, сетевые подключения и многое другое. - person Eric Postpischil; 28.02.2020
comment
Если указать, что что-то «не определено стандартом», становится более очевидным, что это открыто для определения чего-то еще. Запись о том, что что-то является «неопределенным», ошибочно принимается некоторыми как закрыто и не разрешено, как будто это должно оставаться неопределенным. Это неудачный выбор терминологии в стандартах, и я избегаю его. - person Eric Postpischil; 28.02.2020