Лучше задать вопрос: почему целочисленное переполнение не определено? На практике 99,9% всех процессоров используют дополнение до двух и бит переноса/переполнения. Таким образом, в реальном мире, на уровне ассемблера/кода операции, целочисленные переполнения всегда четко определены. На самом деле большая часть ассемблера или аппаратного языка C в значительной степени зависит от четко определенных целочисленных переполнений (в частности, драйверов для оборудования таймера).
Исходный язык C до стандартизации, вероятно, не рассматривал подобные вещи подробно. Но когда C был стандартизирован ANSI и ISO, они должны были следовать определенным правилам стандартизации. Стандарты ISO не позволяют предвзято относиться к определенной технологии и тем самым давать определенной компании преимущество в конкурентной борьбе.
Поэтому им пришлось учитывать, что некоторые процессоры могут реализовывать неясные вещи, такие как дополнение, «знак и величина» или «некоторый способ, определяемый реализацией». Они должны были разрешить нули со знаком, биты заполнения и другие неясные целочисленные механизмы со знаком.
Из-за этого поведение чисел со знаком стало удивительно нечетким. Вы не можете сказать, что происходит, когда целое число со знаком в C переполняется, потому что целые числа со знаком могут быть выражены в дополнении до двух, дополнении до единицы или, возможно, в каком-то другом безумии, определяемом реализацией. Следовательно, целочисленные переполнения представляют собой неопределенное поведение.
Разумным решением этой проблемы было бы не изобретать какие-то проверки безопасного диапазона, а скорее заявить, что все целые числа со знаком в языке C должны иметь формат дополнения до двух, конец истории. Тогда беззнаковый символ всегда будет от 0 до 127, а переполнение до -128, и все будет четко определено. Но искусственная стандартная бюрократия мешает стандарту стать разумным.
В стандарте C есть много подобных проблем. Выравнивание/заполнение, endianess и т. д.
person
Lundin
schedule
22.08.2012
INTO
). Объявленное намерение Intel заключалось в том, чтобы компиляторы использовали его. Насколько я знаю, никто никогда этого не делал (включая собственные компиляторы Intel); исходный компилятор PL/M, который я использовал на 8086, имел возможность использовать его, но на самом деле он не был реализован. - person James Kanze   schedule 22.08.2012