Переполнение

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

Описание

Это начинает работу, арифметическая операция определяет, переполняется ли результат. Результат этой проверки зависит от того, позволяете ли вы неличные результаты плавающие, такие как бесконечность и 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)
 {
   unsigned int i;

   i = 1090654225 << 1; 
 }

В этом примере ошибка 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()
{
  Week.dayOfWeek = 2;
  Week.dayOfWeek = 3;
  Week.dayOfWeek = 4;
}

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

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

enum tBit {
  ZERO = 0x00,
  ONE = 0x01 ,
  TWO = 0x02
};

struct twoBit
{
  enum tBit myBit:2;
} myBitField;

void main()
{
  myBitField.myBit = ZERO;
  myBitField.myBit = ONE;
  myBitField.myBit = TWO; 
}

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

Чтобы обнаружить переполнение на одних только целых числах со знаком, на панели Configuration, под Check Behavior, выбирают forbid или warn-with-wrap-around for Overflow mode for signed integer и allow for 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