2014-09-21 5 views
1

Я читал об этой функции:Почему x - y не переполняется для TMin в этой функции? Почему в этом случае функция неправильная?

int tadd_ok (int x, int y) { 
    int sum = x + y; 
    int negative_overflow = x < 0 && y < 0 && sum >= 0; 
    int positive_overflow = x >=0 && y >= 0 && sum < 0; 
    return !negative_overflow && !positive_overflow; 
} 

Этой функция имеет проблему, когда мы переходим в качестве аргумента для у Tmin (т.е. самых маленьких 2 дополнения).
В этом случае -y будет -y, когда передано в i.e все еще будет TMin, первое условие покажет, что мы имеем отрицательное переполнение для отрицательных значений x.
Затем я прочитал, что на самом деле «x - y не переполняется» в этих случаях.

Я понимаю, что проблема этой функции заключается в том, что она не учитывает угловой случай прохождения минимального отрицательного числа. Я вижу, что он вернет negative_overflow, который я не вижу/не понимаю, почему это неправильно.
Может ли кто-нибудь помочь мне понять это?

+0

Проблема с этой функцией заключается в попытке обнаружить переполнение * после того, как оно могло произойти. Это неправильно, поскольку в случае переполнения носовые демоны уже имели место. – ouah

+0

@ouah: Я думаю, что правильная функция пытается обнаружить до того, как это произойдет? Я не знаю, в чем разница этих подходов. Помимо этого ошибочного подхода, почему TMin считается не переполнением? – Cratylus

+1

Проблема в том, что, как сказал ouah, компилятор C пытается вас навредить, а не помогать. Вместо того, чтобы подписывать переполнение целых чисел с использованием арифметики дополнений 2s, а затем позволяя вам проверять полученную сумму, многие компиляторы C предполагают, что oevrflow никогда не сможет помочь и оптимизировать вашу проверку переполнения. Для получения дополнительной информации см. [Этот вопрос] (http://stackoverflow.com/questions/3944505/detecting-signed-overflow-in-c-c) – hugomg

ответ

3

Вы не можете проверить, не произошло ли переполнение целого числа после факта, вы должны проверить перед выполнением операции. Это связано с тем, что целочисленное переполнение целых чисел в арифметической операции равно undefined behavior в C, а также в C++. Когда вы вызываете неопределенное поведение, результат вашей программы становится непредсказуемым (see my comment above for one of the most unexpected results I have seen). Для C, мы можем увидеть, перейдя в draft C99 standard секции 6.5Выражения, который говорит:

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

Cert дает твердое руководство о том, как предотвратить подписанное переполнение: INT32-C. Ensure that operations on signed integers do not result in overflow и для дополнений документа рекомендует следующий способ:

#include <limits.h> 

void f(signed int si_a, signed int si_b) { 
    signed int sum; 
    if (((si_b > 0) && (si_a > (INT_MAX - si_b))) || 
     ((si_b < 0) && (si_a < (INT_MIN - si_b)))) { 
    /* Handle error */ 
    } else { 
    sum = si_a + si_b; 
    } 
    /* ... */ 
} 

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

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

  • Нет связанных вопросов^_^