Если вам требуется такое поведение, используйте числа с плавающей запятой, которые могут представлять бесконечность, и обеспечивают желаемое поведение.Обратите внимание, что технически это неопределенное поведение , но на практике большинство компиляторов ( все основные компиляторы для стандартных архитектур) реализуют семантику IEEE 754, например, GCC .
int main() {
float f = 42;
float g = f / 0.0f;
printf("%f\n", g);
}
Вывод:
inf
Это поведение, на которое можно положиться , поскольку оно четко задокументировано компиляторами.Однако при написании переносимого кода убедитесь, что вы проверяете эти предположения внутри своего кода (например, проверяя, определены ли макросы препроцессора __STDC_IEC_559__
, , а также макросы для конкретного компилятора ).
Если по каким-то причинам вам нужно такое поведение для целочисленных значений, единственным выходом является создание собственного типа.Примерно так:
typedef struct {
int value;
bool is_inf;
bool is_nan;
} ext_int;
ext_int make_ext_int(int i) {
return (ext_int) {i, false, false};
}
ext_int make_nan() {
return (ext_int) {0, false, true};
}
ext_int make_inf(int sign) {
return (ext_int) {(sign > 0) - (sign < 0), true, false};
}
ext_int ext_div(ext_int a, ext_int b) {
if (a.is_nan || b.is_nan) {
return make_nan();
}
if (b.value == 0) {
return make_inf(a.value);
}
// TODO: insert other cases.
return (ext_int) {a.value / b.value, false, false};
}
… в реальной реализации вы бы упаковывали разные флаги, вместо того, чтобы иметь, конечно, отдельный bool
для каждого.