Overflow

Арифметическая операция вызывает переполнение

Описание

Это начинает работу, арифметическая операция определяет, переполняется ли результат. Результат этой проверки зависит от того, позволяете ли вы неличные результаты плавающие, такие как бесконечность и NaN.

Результат проверки также зависит от плавающего режима округления, который вы задаете. По умолчанию округляющимся режимом является to-nearest. Смотрите Float rounding mode (-float-rounding-mode).

Неличные плавания, не позволенные

По умолчанию неличные плавания не позволены. Когда результат операции выходит за пределы позволенной области значений, переполнение происходит. Проверка:

  • Красный, если результат операции выходит за пределы позволенной области значений.

  • Оранжевый, если результат операции выходит за пределы позволенной области значений на некоторых путях к выполнению.

  • Зеленый, если результат операции не выходит за пределы позволенной области значений.

Чтобы точно настроить поведение проверки переполнения, используйте эти опции и задайте аргумент forbid, allow, или warn-with-wrap-around:

Типы данных операнда определяют позволенную область значений для арифметической операции. Если операция включает два операнда, верификация использует правила преобразования ANSI® C, чтобы определить тип общих данных. Этот тип общих данных определяет позволенную область значений.

Для некоторых примеров правил преобразования смотрите Неявные Преобразования типа данных.

Неличные позволенные плавания

Если вы включаете режим верификации, который включает бесконечности, и укажите, что верификация должна предупредить об операциях, которые производят бесконечности, проверка:

  • Красный, если операция производит бесконечность на всех путях к выполнению, которые программное обеспечение рассматривает, и сами операнды, весьма конечны.

  • Оранжевый, если операция производит бесконечность на некоторых путях к выполнению, когда сами операнды весьма конечны.

  • Зеленый, если операция не производит бесконечность, если сами операнды не бесконечны.

Если вы указываете, что верификация должна запретить операции, которые производят бесконечности, цвет проверки зависит от результата операции только. Цвет не зависит от операндов.

Чтобы включить этот режим верификации, используйте эти опции:

Примеры

развернуть все

void main() {
  int i=1;
  i = i << 30; //i = 2^30
  i = 2*i-2;
}

В этом примере, операции 2*i результаты в значении 231. Overflow начинает работу, умножение производит красную ошибку потому что максимальное значение что тип int может держаться 32-битной целью является 231-1.

void main(void)
 {
   int i;
   int shiftAmount = 1;

   i = 1090654225 << shiftAmount; 
 }

В этом примере происходит ошибка Overflow, сдвиг влево выполняется на целом числе со знаком.

#include <float.h>

void main() {
 float val = FLT_MAX;
 val = val * 2 + 1.0;
}

В этом примере, FLT_MAX максимальное значение что float может представлять на 32-битной цели. Поэтому операция val * 2 результаты по ошибке Overflow.

void func(void) {
   float fVal = -2.0f;
   unsigned int iVal = (unsigned int)fVal; 
}

В этом примере красная проверка Overflow появляется на броске от float к unsigned int. Согласно Стандарту C99 (сноска к абзацу 6.3.1.4), областью значений значений, которые могут быть преобразованы от значений с плавающей точкой до беззнакового целого при хранении кода портативным, является (-1, MAX + 1). Для значений с плавающей точкой вне этой области значений преобразование в беззнаковое целое не четко определено. Здесь, MAX максимальное количество, которое может храниться типом беззнаковых целых чисел.

Даже если ошибка времени выполнения не происходит, когда вы выполняете код на своей цели, состав исполнителей может перестать работать на другой цели.

Коррекция — бросок к целому числу со знаком сначала

Одно возможное решение состоит в том, чтобы бросить значение с плавающей точкой к целому числу со знаком сначала. Целое число со знаком может затем быть брошено к типу беззнаковых целых чисел. Для этих бросков правила преобразования четко определены.

void func(void) {
   float fVal = -2.0f;
   int iValTemp = (int)fVal;
   unsigned int iVal = (unsigned int)iValTemp; 
}
#define FLT_MAX 3.40282347e+38F

void float_negative_overflow() {
   float min_float = -FLT_MAX;
   min_float = -min_float * min_float;
}

В float_negative_overflow, min_float содержит наиболее отрицательное число что тип float может представлять. Поскольку операция -min_float * min_float производит номер, который более отрицателен, чем этот номер, тип float не может представлять его. Проверка Overflow производит красную ошибку.

#include <stdio.h>

struct
{
  unsigned int dayOfWeek : 2;
} Week;

void main()
{
  unsigned int two = 2, three = 3, four = 4;
  Week.dayOfWeek = two;
  Week.dayOfWeek = three;
  Week.dayOfWeek = four;
}

В этом примере, dayOfWeek занимает 2 бита. Это может принять значения в [0,3] потому что это - беззнаковое целое. Когда вы присваиваете значение 4 dayOfWeek, проверка Overflow является красной.

Чтобы обнаружить переполнение на целых числах со знаком и беззнаковом целом, на панели Configuration, под Check Behavior, выбирают forbid или warn-with-wrap-around для Overflow mode for signed integer и Overflow mode for unsigned integer.

Результаты в forbid режим:

double func(void) {
    double x=1.0/0.0;
    return x;
}
В этом примере, оба операнды / операция весьма конечна, но результатом является бесконечность. Overflow проверяет - операция является красной. В forbid режим, остановки верификации после красной проверки. Например, проверка Non-initialized local variable не появляется на x в return оператор. Если вы не включаете опцию Allow non finite floats, проверка Division by zero появляется, потому что бесконечности не позволены.

Результаты в warn-first режим:

double func(void) {
    double x=1.0/0.0;
    return x;
}
В этом примере, оба операнды / операция весьма конечна, но результатом является бесконечность. Overflow проверяет - операция является красной. Красные регистрации warn-first режим отличается от красных проверок на другие типы проверки. Верификация не останавливается после красной проверки. Например, зеленая проверка Non-initialized local variable появляется на x в return оператор. В результате верификации, если вы устанавливаете свой курсор на x, вы видите, что это имеет значение Inf.

Результаты в forbid режим:

void func(double arg1, double arg2) {
    double ratio1=arg1/arg2;
    double ratio2=arg1/arg2;
}
В этом примере, значениях arg1 и arg2 неизвестны верификации. Верификация принимает тот arg1 и arg2 может иметь весь возможный double значения. Например, arg1 может быть ненулевым и arg2 может быть нуль и результат ratio1=arg1/arg2 может быть бесконечность. Поэтому оранжевая проверка Overflow появляется на операции деления. После проверки верификация отключает поток выполнения, который приводит к бесконечности. Верификация принимает тот arg2 не может быть нуль после оранжевой проверки. Overflow проверяет вторую операцию деления ratio2=arg1/arg2 является зеленым.

Результаты в warn-first режим:

void func(double arg1, double arg2) {
    double ratio1=arg1/arg2;
    double ratio2=arg1/arg2;
}
В этом примере, значениях arg1 и arg2 неизвестны верификации. Верификация принимает тот arg1 и arg2 может иметь весь возможный double значения. Например, arg1 может быть ненулевым и arg2 может быть нуль и результат ratio1=arg1/arg2 может быть бесконечность. Оранжевая проверка Overflow появляется на операции деления. Оранжевые регистрации warn-first режим отличается от оранжевых проверок на другие типы проверки. После проверки верификация не отключает поток выполнения, который приводит к бесконечности. Верификация сохраняет нулевое значение arg2 после оранжевой проверки. Поэтому Overflow проверяет вторую операцию деления ratio2=arg1/arg2 является также оранжевым.

Проверяйте информацию

Группа: числовой
Язык: C | C++
Акроним: OVFL