2014-11-02 2 views
3

Я не сомневаюсь в необходимости проверки деления на ноль. Я никогда не слышал о проверке деления на отрицательный, хотя!Ошибка выполнения во время деления на -1

if(*y == 0) 
    return 0; //undefined 
else 
    return *x/*y; 

x, y являются указателями на int32_t, я включаю эту деталь в случае релевантности.

Во время выполнения, если *x==0x80000000, *y==0xffffffff, я получаю сообщение об ошибке (в Xcode):

EXC_ARITHMETIC (код = EXC_I386_DIV, субкодовое = 0x0)

Все, что я могу найти в Интернете является Предложения, является делением на ноль, но, как вы можете видеть из вышеприведенного теста, и я вижу из окна отладки, это не так.

Что означает ошибка, и как я могу ее исправить?

+1

Если 'y == 0xffffffff', то это вряд ли допустимый указатель на int32_t, как вы утверждаете. –

+0

@Paul Спасибо - typo, я имел в виду '* y' – OJFord

+0

См. [Почему unsigned int 0xffffffff равно int -1] (http://stackoverflow.com/questions/1863153/why-unsigned-int-0xffffffff-is- equ-to-int-1) для обсуждения представления чисел и того, как на разных машинных архитектурах есть некоторые числа, такие как нуль и отрицательный, представление которых может варьироваться. –

ответ

12

Представление комплемента 2 является асимметричным: есть еще одно отрицательное число, чем положительное число, и это отрицательное число не имеет положительного аналога. Следовательно, отрицание MIN_INT представляет собой целочисленное переполнение (где MIN_INT - это значение, единственное 1-бит - знаковый бит, 0x80000000 для 32-разрядных целых чисел).

MIN_INT/-1 есть, поэтому, также арифметическое переполнение. В отличие от переполнения от вычитания (который редко проверяется), переполнение при делении может вызвать ловушку, и, по-видимому, это то, что происходит в вашем случае.

И, да, с технической точки зрения, перед делением следует проверить на предмет переполнения MIN_INT/-1, поскольку результат не определен.

Примечание: В общем случае архитектуры Intel x64, перелив разделение делает ловушку, точно так же, как деление на 0. Смутно, соответствующий сигнал Posix является SIGFPE, который обычно мыслится как «плавающей точкой» Exception, хотя плавающей точки нет. Текущий стандарт Posix фактически блестит SIGFPE как означающий «Erroneous Arithmetic Operation».

+3

Есть ли «лучшая практика» для чего? например, решить, что результат равен нулю, или 'INT_MAX', или что-то еще? – OJFord

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