После выполнения математической операции, например, умножения двух целых чисел, можно ли получить доступ к регистру флага переполнения в ЦП с C++? Если нет, то каковы другие быстрые способы проверки переполнения?
Можно ли получить доступ к регистру флага переполнения в ЦП с С++?
Ответы (5)
Нет, вообще это невозможно. Некоторые процессоры даже не имеют такого флага (например, MIPS).
ссылка, представленная в одном из комментариев, даст вам идеи о том, как вы можете выполнять проверки переполнения.
Помните, что в C и C++ переполнения целых чисел со знаком вызывают неопределенное поведение, и по закону вы не можете выполнять проверки переполнения постфактум. Вам нужно либо использовать беззнаковую арифметику, либо выполнять проверки перед арифметическими операциями.
Я рекомендую это чтение в каждом подходящем случае. Из Оптимизация программного обеспечения на C++ -
Целочисленное переполнение — еще одна проблема безопасности. Официальный стандарт C говорит, что поведение целых чисел со знаком в случае переполнения "не определено". Это позволяет компилятору игнорировать переполнение или предположить, что оно не происходит. В случае с компилятором Gnu предположение об отсутствии переполнения целого числа со знаком имеет неблагоприятное последствие, заключающееся в том, что оно позволяет компилятору оптимизировать проверку переполнения. Существует ряд возможных способов решения этой проблемы: (1) проверять переполнение до того, как оно произойдет, (2) использовать целые числа без знака — они гарантированно переходят друг в друга, (3) перехватывать целочисленное переполнение с помощью параметра
-ftrapv
, но это чрезвычайно неэффективно, (4) получить предупреждение компилятора о такой оптимизации с помощью опции-Wstrict-overflow=2
или (5) четко определить поведение переполнения с помощью опции-fwrapv
или-fno-strict-overflow
.
Вам нужно будет выполнить операцию и проверить бит переполнения во встроенной сборке. Вы можете сделать это и перейти к метке при переполнении или (в более общем случае, но менее эффективно) установить переменную, если она переполнится.
Нет. Лучший способ проверить заранее, как здесь
Если нет, то каковы другие быстрые способы проверки переполнения?
Если вам нужно протестировать после операции, вы можете использовать представление с плавающей запятой (двойная точность) - каждое 32-битное целое число может быть представлено точно как число с плавающей запятой. Если все машины, на которые вы нацелены, поддерживают IEEE (что, вероятно, так и есть, если вам не нужно рассматривать мейнфреймы), вы можете просто выполнять операции, а затем использовать isfinite или isinf для результатов. Быстрый (с точки зрения усилий программиста) способ: Стандарт IEEE для арифметики с плавающей запятой (IEEE 754) определяет пять исключений, каждое из которых возвращает значение по умолчанию и имеет соответствующий флаг состояния, который (за исключением некоторых случаев потери значимости) возникает при возникновении исключения. Пять возможных исключений:
- Недопустимая операция: математически неопределенная, например, квадратный корень из отрицательного числа. По умолчанию возвращает qNaN.
- Деление на ноль: операция над конечными операндами дает точный бесконечный результат, например, 1/0 или log(0). По умолчанию возвращает ±бесконечность.
- Переполнение: результат слишком велик для правильного представления (т. е. его показатель степени с неограниченным диапазоном показателей будет больше, чем emax). По умолчанию возвращает ±бесконечность для режимов округления до ближайшего (и следует правилам округления для режимов направленного округления).
- Underflow: результат очень маленький (за пределами нормального диапазона) и неточный. По умолчанию возвращает субнормальное значение или ноль (в соответствии с правилами округления).
- Неточный: точный (т.е. неокругленный) результат не может быть точно представлен. По умолчанию возвращает правильно округленный результат.
fenv
: en.cppreference.com /w/c/числовой/fenv. fetestexcept(FE_OVERFLOW)
проверяет флаг переполнения FP. (Правильно работает, только если вы используете #pragma STDC FENV_ACCESS ON
или параметры командной строки для некоторых компиляторов. ru. cppreference.com/w/c/numeric/fenv/fetestexcept есть пример.)
- person Peter Cordes; 12.04.2020
double
может представлять каждый int32_t
, но не каждый int64_t
. Так что да, вы можете проверить диапазон double
перед преобразованием обратно в int
. Это вряд ли эффективно, так что ИДК, в чем ваша точка зрения. Некоторые машины будут иметь 80-битную или более широкую long double
, которая может представлять каждую int64_t
, но многие реализации C++ имеют только 64-битную FP. Кроме того, переполнение FP не имеет отношения к этой проблеме (если только вы не выполняете несколько умножений, которые фактически приводят к переполнению FP).
- person Peter Cordes; 13.04.2020
double
, но первое непредставимое целочисленное double
равно 2^53 + 1, потому что оно имеет 53-битную мантисса. en.wikipedia.org/wiki/Double-precision_format_floating-point. 64-битный double
может представлять некоторые числа, отличные от возможных значений int64_t
, поэтому по принципу сортировки должны быть некоторые значения int64_t
, которые не имеют double
битового шаблона для их представления. См. Какое первое целое число не может быть точно представлено числом с плавающей запятой IEEE 754?
- person Peter Cordes; 13.04.2020
double
также имеет множество нецелочисленных значений. Половина double
битовых шаблонов представляют значения от -1,0 до +1,0, и между меньшими целыми числами есть много дробных значений. (К вашему сведению, английское слово, которое вы здесь ищете, правильное, а не писать. Произносится одинаково, пишется по-разному.) Я не только что изобрел это доказательство; это общеизвестный факт. Но рад, что смог помочь и указать на это вам. В любом случае, вам может понравиться randomascii.wordpress. com/2012/02/25/ — отличная серия статей о FP
- person Peter Cordes; 13.04.2020
Это, вероятно, не то, что вы хотите сделать по двум причинам:
- не каждый процессор имеет флаг переполнения
- используя С++, на самом деле нет способа получить доступ к флагу переполнения
советы по проверке переполнения, которые люди размещали ранее, могут быть полезны.
если вы действительно хотите написать очень быстрый код, который умножает два целых числа и проверяет флаг переполнения, вам придется использовать ассемблер. если вам нужны примеры для x86, то спрашивайте