Люди жалуются, что следующий код выдаёт ошибку:
const B = Byte(1); C: Byte = not B; // Constant expression violates subrange bounds (*)Они говорят: "Результат операции с 'Byte' должен быть ещё одним 'Byte', а не 'Integer'".
Будьте осторожны в своих желаниях. Они могут вам не понравиться.
Предположим, мы бы жили в вымышленном мире, где операции с 'Byte' приводят к результату в виде 'Byte'.
const B: Byte = 32; C: Byte = 240; var I: Integer; begin I := B + C; // Чему равно I?В этом вымышленном мире, значение I было бы 16! Почему? Потому что оба операнда в операторе + являются Byte, поэтому сумма "B + C" также будет Byte, что приводит к результату 16 из-за переполнения (и, как я уже заметил ранее, целочисленные переполнения являются новым вектором атак).
Аналогично,
I := -B;приведёт к тому, что I будет равно 224 а не -32, по той же причине.
Вы действительно хотите этого?
Рассмотрим следующий более тонкий сценарий:
type TResults = record Wins: Byte; Games: Byte; end; function WinningAverage(const Captain, CoCaptain: TResults): Bool; begin Result := (Captain.Wins + CoCaptain.Wins) >= ((Captain.Games + CoCaptain.Games) div 2); end;В нашем воображаемом мире этот код возвращал бы неверные значения, если суммарное число сыгранных матчей превысило бы 255. Для исправления вам пришлось бы вставлять эти надоедливые приведения типов:
function WinningAverage(const Captain, CoCaptain: TResults): Bool; begin Result := (Integer(Captain.Wins) + CoCaptain.Wins) >= ((Integer(Captain.Games) + CoCaptain.Games) div 2); end;Получается: что бы вы ни сделали - всё равно в каком-то случае вам придётся вставлять преобразования типов. И уж лучше иметь ошибку языка на стороне безопасности (когда компилятор принуждает вас вставлять явное преобразование в те места, где вы уверены, что там нет проблем с переполнением), чем на стороне тихого скрытия проблемы (когда вы можете не заметить пропущенные преобразования, пока ваш отдел бухгалтерии не спросит вас, а чего это у них в конце месяца цифры не сходятся).
Примечание переводчика:
(*) На самом деле, более правильным объявлением было бы B: Byte = 1;, но проблема в том, что компилятор не считает такое объявление за константу (да, даже при выключенной опции Assignable typed constants), поэтому во втором объявлении будет ошибка "Constant expression expected".
Комментариев нет:
Отправить комментарий
Можно использовать некоторые HTML-теги, например:
<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>
Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.
Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.
Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.
Примечание. Отправлять комментарии могут только участники этого блога.