2010-04-13 6 views
20

Можно создать дубликат:
Best way to detect integer overflow in C/C++Как проверить переполнение целых чисел в C?

Там это (1):

// assume x,y are non-negative 
if(x > max - y) error; 

И (2):

// assume x,y are non-negative 
int sum = x + y; 
if(sum < x || sum < y) error; 

Whichs является prefe rred или есть лучший способ.

+0

На самом деле дубликат не дубликат вообще, это говорит о 'unsigned', которые четко определенный запах семантики, в то время как переполнение целого числа не определенно поведение в C. –

+2

Там нет необходимости проверять и 'sum

ответ

-5

Вам нужно только проверить один из них. Если x + y переполняется, он будет меньше, чем x и y. Следовательно:

int sum = x + y; 
if (sum < x) error; 

должно быть достаточным.

Следующий сайт имеет кучу вещей о целочисленном переполнении:

http://www.fefe.de/intof.html

Если вы хотите, чтобы справиться с отрицательными числами, он может быть расширен:

int sum = x + y; 
if (y >= 0) { 
    if (sum < x) error; 
} else { 
    if (sum > x) error; 
} 
+1

Что делать, если 'y' отрицательно? –

+1

Исходный плакат задал неотрицательные целые числа, но я добавил код для обработки отрицательных чисел. – clahey

+18

Это неверно - после переполнения 'x + y' программа имеет неопределенное поведение.У вас есть *, чтобы проверить, прежде чем выполнять операцию переполнения - так же, как и для целочисленного деления на ноль. – caf

6

Вы можете действительно только чек для переполнения unsigned целые и арифметические значения:

unsigned a,b,c; 
a = b + c; 
if (a < b) { 
    /* overflow */ 
} 

Поведение переполнения с целыми числами не определен в C, но на большинстве машин вы можете использовать

int a,b,c; 
a = b + c; 
if (c < 0 ? a > b : a < b) { 
    /* overflow */ 
} 

Это не будет работать на компьютерах, использующих любой вид насыщать арифметику

+4

Проверка переполнения после факта со знаками целых чисел неверна. Это неопределенное поведение, поэтому компиляторы с радостью оптимизируют проверки, не передавая такой переключатель, как '-fwrapv', чтобы включить подпись в качестве расширения языка. Это не просто проблема переносимости в архитектуре. – strcat

+1

Также можно проверить переполнение целых чисел со знаком. См. Https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow – sbhatla

47

Целочисленного переполнения является канонический пример «неопределенного поведения» в C (отмечая, что операции с целыми целыми без знака никогда не переполняются, они определяются вместо обхода). Это означает, что после того, как вы выполнили x + y, если он переполнен, вы уже были заняты. Слишком поздно делать какие-либо проверки - ваша программа, возможно, уже разбилась. Подумайте, как проверить деление на ноль - если вы подождете, пока после того, как деление будет выполнено, чтобы проверить, уже слишком поздно.

Таким образом, это означает, что метод (1) является единственным правильным способом его выполнения. Для max вы можете использовать INT_MAX от <limits.h>.

Если x и/или y может быть отрицательным, тогда все сложнее - вам нужно выполнить тест таким образом, чтобы сам тест не мог вызвать переполнение.

if ((y > 0 && x > INT_MAX - y) || 
    (y < 0 && x < INT_MIN - y)) 
{ 
    /* Oh no, overflow */ 
} 
else 
{ 
    sum = x + y; 
} 
+5

Если вы идущий к downvote, считается учтивым оставить комментарий, объясняющий то, что вы считаете бесполезным или неправильным. – caf

+0

Btw, можете ли вы прокомментировать эффективность этого решения по сравнению с другими альтернативными решениями? – Pacerier

+6

Не имеет смысла сравнивать производительность с неправильным решением. Какое другое правильное решение вы имели в виду? – caf

Смежные вопросы