Деление на ноль в C - PullRequest
       12

Деление на ноль в C

0 голосов
/ 02 февраля 2019

Когда я компилирую программу:

#include <stdio.h>

int main(void)
{
    int x, y = 0;

    x = 1 / y;
    printf("x = %d\n", x);
    return 0;
}

Выдает «Исключение с плавающей запятой (ядро сброшено)»

Однако, когда я компилирую:

#include <stdio.h>

int main(void)
{
    double x, y = 0;

    x = 1 / y;
    printf("x = %f\n", x);
    return 0;
}

Он печатает "x = inf"

Почему он возвращает x как бесконечное значение, если вы используете double, но возвращает ошибку, если вы используете int?

Ответы [ 3 ]

0 голосов
/ 02 февраля 2019

Стандарт C прямо заявляет, что деление на ноль имеет неопределенное поведение для целочисленных операндов или операндов с плавающей запятой.

C11 6.5.5 параграф 5:

Результат/ оператор - это частное от деления первого операнда на второй;результат оператора % - остаток.В обеих операциях, если значение второго операнда равно нулю, поведение не определено.

Неопределенное поведение означает, что стандарт ничего не говорит о том, что происходит.Это может привести к значимому или бессмысленному результату, может потерпеть крах или, как говорится в стандартной шутке, заставить демонов вылететь из носа.(Конечно, этого не произойдет, но это не нарушит стандарт С, если бы он это сделал.)

Типы с плавающей запятой, в отличие от целочисленных типов, часто имеют специальные значения, которые не представляютномера.Стандарт IEEE с плавающей точкой определяет, что деление на ноль может привести к результату Infinity, что и делает ваша реализация.Для целых чисел значения "Бесконечность"(Обратите внимание, что реализации C могут соответствовать или не соответствовать стандарту IEEE с плавающей запятой.)

В этом вопросе обсуждается семантика деления на ноль в плавающей запятой IEEE.

0 голосов
/ 02 февраля 2019
Стандарт

C определяет, что поведение деления на ноль для операндов арифметических типов не определено (см., Например, этот стандартный черновик C):

6.5.5 Мультипликативные операторы

2 Каждый из операндов должен иметь арифметический тип.Операнды оператора% должны иметь целочисленный тип.

5 Результатом оператора / является частное от деления первого операнда на второй;результат оператора% - остаток.В обеих операциях, если значение второго операнда равно нулю, поведение не определено.

И это правило явно включает в себя значения с плавающей запятой, поскольку термин арифметических типов означает целое числозначения и значения с плавающей запятой:

6.2.5 Типы

18 Целочисленные и плавающие типы вместе называются арифметическими типами.

Следовательно, оба ваших примера на самом деле являются неопределенным поведением, и каждый компилятор может самостоятельно указать, как обращаться с вашими утверждениями.И, таким образом, он соответствует стандарту, если компилятор рассматривает деление на ноль как исключение, тогда как деление на ноль с плавающей точкой дает специальное значение inf.Примечание: стандарт не определяет, что это должно быть так.

0 голосов
/ 02 февраля 2019

Переменная с плавающей точкой может фактически хранить значение, представляющее бесконечность.(Это значение INFINITY, определенное в math.h.) Но нет целочисленного представления бесконечности, поэтому единственное, что нужно сделать, - это потерпеть неудачу.

...