2

modf()函数族都带有一个指针参数:

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

用于返回其输入的整数部分arg(小数部分是实际返回值)。

如果我只需要小数部分,我可以通过传递“跳过”积分部分的计算NULL吗?

我喜欢的 cppreference 页面都没有,也没有说明传递forman modff时会发生什么,而其他一些标准库函数将 NULL 作为“忽略此参数”的指示。NULLiptr

4

5 回答 5

2

根据ISO/IEC 9899:2017草案:

F.10.3.12 modf 函数

...

...

3 modf 的行为就像由

    #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);
    }

所以,我会说你不能。

于 2021-01-05T12:20:34.490 回答
2

正如其他答案所暗示的那样,您不能通过NULL- 或者至少,您不能依靠能够通过NULL

相反,使用这样的东西:

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

同样对于doublelong double

于 2021-01-05T13:38:55.660 回答
2

标准没有定义这个

描述

2 modf 函数将参数值分解为整数和小数部分,每个部分都具有与参数相同的类型和符号。它们将整数部分(以浮点格式)存储在 iptr 指向的对象中。

退货

3 modf 函数返回值的有符号小数部分。

因此传递时的行为NULL将是未定义的。您可能会发现一些允许它的编译器,但任何依赖于此的代码都不可移植(即使在同一编译器的版本之间)。

于 2021-01-05T12:18:23.993 回答
2

我可以将 NULL 传递给 modf/modff 吗?

modf(double arg, double* iptr)和朋友在iptr == NULL. 传递 aNULL未定义的行为(UB)。

如果代码想要一个不需要保存整数部分以供以后使用的单行,请考虑为临时使用复合文字double并相信编译器能够优化。

#include <math.h>

double fraction(double x) {
  return modf(x, &(double){0});
}
于 2021-01-05T15:32:30.993 回答
1

手册页没有提到这种使用函数的方式,如果我们查看 glibc 实现,它肯定没有处理这种情况:

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

所以不,这不是你可以合法做的事情。

此外,C99 对 modf 的评价是:

modf 函数将参数值分解为整数和小数部分,每个部分都具有与参数相同的类型和符号。它们将整数部分(以浮点格式)存储在 iptr 指向的对象中。

所以 glibc 的实现完全符合标准。

于 2021-01-05T12:14:11.180 回答