Question Details

No question body available.

Tags

c floating-point math.h c23

Answers (4)

Accepted Answer Available
Accepted Answer
December 15, 2025 Score: 31 Rep: 932 Quality: Expert Completeness: 100%

In fact... They’re almost the same check, but not quite, once you look at the formal semantics.

For a "normal" IEEE-754 implementation and an ordinary finite value of x, these two:

iszero(x)

and

x == 0

will both be true exactly when x is either +0 or -0, and false otherwise. So for everyday code on typical hardware, you won’t see a difference

The reasons iszero exists are more subtle and mostly about FP semantics and consistency with the other classification macros:

1. iszero is a classification operation, not an arithmetic comparison

iszero is part of the same family as fpclassify, isfinite, isnan (...) . In C23 these are specified to implement the corresponding IEC 60559 (IEEE-754) classification operations. The standard explicitly says that these macros:

provide the IEC 60559 operations … Then these macros raise no floating-point exceptions, even if an argument is a signaling NaN

reviews.llvm.org

So:

  • iszero(x) is required not to raise floating-point exceptions (even if you pass a signaling NaN)

  • x == 0 is a normal floating-point comparison and may raise FE_INVALID if x is a signaling NaN, per IEC 60559 comparison rules

On most platforms you never see signaling NaNs in practice, so you don’t notice this. But at the spec level, they are not the same operation (because they didn't call the same space in asm)


2. Type-generic & library consistency

iszero is defined only for real floating types and participates in the C23 type-generic math API (binary floats, decimal floats, extended types). It’s there so you can write code that classifies values purely via the classification layer:

if (iszero(x))       { / zero / }
else if (isnan(x))   { / NaN / }
else if (isinf(x))   { / infinity / }

That’s cleaner and more uniform than mixing:

if (x == 0)          / classification by comparison /
if (isnan(x))        / classification macro /

3. What about +0 vs -0?

Both operations ignore the sign of zero in the same way:

So there’s no sign-of-zero difference between them. I tested on the online gcc (with recreated the same macro) and I have the same result in local (without re-created the macro like gcc online)


So when should I care?

  • If you just want to know "is this value zero?" in ordinary numerical code:
    x == 0 and iszero(x) behave the same for all non-NaN values

  • If you care about strict IEEE / C23 semantics, iszero is the correct tool:

    • It’s guaranteed not to raise FP exceptions

    • It fits with the other classification macros and works uniformly across all supported floating types

In other words: for most practical purposes they act the same, but the standard gives iszero stricter, exception-free classification semantics that x == 0 doesn’t promise

December 15, 2025 Score: 14 Rep: 191,605 Quality: Expert Completeness: 80%

@Asile34's answer covers the main points very well, but brushes over / omits a few.

iszero(x) is specified only for real floating types

... as opposed to complex floating types. On the other hand, the behavior of == is defined for any pair of operands of arithmetic type. Thus, this ...

double Complex x = 0;

if (x == 0) { // do something ... } else { // fail }

... has well-defined behavior, but the corresponding iszero() code ...

double Complex x = 0;

if (iszero(x)) { //
December 17, 2025 Score: 3 Rep: 31 Quality: Medium Completeness: 80%

The primary difference—other than real vs. complex inputs, and whether nonzero results are exactly 1—is whether it raises a floating-point exception:

  • x == 0 may raise an exception some inputs, leading fetestexcept to report sticky exception bits having been set, possibly leading to a trap such as SIGFPE.
  • iszero(x) never raises an exception on any input.

On a C implementation supporting Annex F, IEC 60559 floating-point arithmetic (more widely known as IEEE 754 floating-point arithmetic), the following two fragments can be distinguished by passing, as the value of x, a signalling NaN value, such as the IEEE binary64 values encoded by 0x7ff8000000000000 or 0x7ff0000000000001, depending on the machine architecture (0x7ff0000000000001 is signalling on most architectures, except hppa and mips where it is quiet and 0x7ff8000000000000 is signalling):

  1. x == 0

    #pragma FENV STDCACCESS ON

    feclearexcept(FEALLEXCEPT); bool result = (x == 0); if (fetestexcept(FEINVALID)) printf("invalid operation\n"); printf("result = %d\n", result);

    • If FEINVALID is trapped, e.g. with the nonstandard but widespread feenableexcept(FEINVALID): traps, typically with SIGFPE.
    • If FEINVALID is not trapped: prints invalid operation and then result = 0.
  2. iszero(x)

    #pragma FENVSTDCACCESS ON

    feclearexcept(FEALLEXCEPT); bool result = iszero(x); if (fetestexcept(FEINVALID)) printf("invalid operation\n"); printf("result = %d\n", result);

    Always prints result = 0, never prints invalid operation and never traps.

December 15, 2025 Score: 1 Rep: 152,758 Quality: Low Completeness: 40%

In addition to Asile34 and John Bollinger's answers, it should be noted that f == 0.0 may generate a compiler warning as comparing floating point with == or != is unsafe, whereas iszero should not, as long as the compiler supports this new macro, introduced in C23.