Can I pass NULL to modf/modff?

582 views Asked by At

The modf() family of functions all take a pointer parameter:

float       modff( float arg, float* iptr );
double      modf( double arg, double* iptr );
long double modfl( long double arg, long double* iptr );

for returning the integral part of their input arg (the fractional part is the actual return value).

If I only need the fractional part, can I "skip" the computation of the integral part by passing NULL?

Neither the cppreference page I liked to, nor man modff, say anything about what happens when you pass NULL for iptr, while some other standard library functions take NULL as an indication of "ignore this parameter".

5

There are 5 answers

4
chux - Reinstate Monica On

Can I pass NULL to modf/modff?

modf(double arg, double* iptr) and friends lack defined functionality when iptr == NULL. Passing a NULL is undefined behavior (UB).

If code wants a one liner that does not need to save the integer part for later use, consider a compound literal for the temporary double and trust the compiler to optimize as able.

#include <math.h>

double fraction(double x) {
  return modf(x, &(double){0});
}
0
einpoklum On

As others answers suggest, you can't pass NULL - or at least, you can't rely on being able to pass NULL.

Instead, use something like this:

inline float fractional_part_float( float arg ) {
    float integral_part;
    return modff(arg, &integral_part);
}

and similarly for double and long double.

0
AudioBubble On

Man pages do not mention this way of using the function and if we look at the glibc implementation, it definitely doesn't have handling for that case:

https://code.woboq.org/userspace/glibc/sysdeps/ieee754/dbl-64/wordsize-64/s_modf.c.html

So no, that's not a thing you can legally do.

Also all that C99 has to say about modf is:

The modf functions break the argument value into integral and fractional parts, each of which has the same type and sign as the argument. They store the integral part (in floating-point format) in the object pointed to by iptr.

so the glibc implementation is perfectly fine in its conformance to the standard.

0
simonc On

The standard doesn't define this

Description

2 The modf functions break the argument value into integral and fractional parts, each of which has the same type and sign as the argument. They store the integral part (in floating-point format) in the object pointed to by iptr.

Returns

3 The modf functions return the signed fractional part of value.

so behaviour when passing NULL will be undefined. You may find some compiler which allows it but any code relying on this would not be portable (even between versions of the same compiler).

3
Mark Benningfield On

According to the ISO/IEC 9899:2017 draft:

F.10.3.12 The modf functions

...

...

3 modf behaves as though implemented by

    #include<math.h>
    #include<fenv.h>
    #pragma STDC FENV_ACCESS ON
    double modf(doublevalue,double*iptr){
        intsave_round =fegetround();
        fesetround(FE_TOWARDZERO);
        *iptr =nearbyint(value);
        fesetround(save_round);
        return copysign(isinf(value) ? 0.0:value - (*iptr), value);
    }

So, I would say that you can't.