modf

时间:2016-11-07 09:03:52

标签: c++ gcc

我对modf的重载解析有疑问。

请考虑以下代码。

#include <iostream>
#include <iomanip>
#include <climits>
#include <cmath>

int main()
{
    unsigned long ul = ULONG_MAX;
    long double ipart;
    long double fpart = std::modf(ul, &ipart);

    std::cout << std::fixed << std::setprecision(0)
        << ul << ", " << ipart << ", " << fpart << '\n'
        << static_cast<double>(ul) << '\n';
}

在我的测试环境中,代码输出......

18446744073709551615, 18446744073709551615, 0
18446744073709551616

比照http://melpon.org/wandbox/permlink/7ZF2CwqEwBRU5hg4

C ++ 14标准26.8 [c.math] p.11说,

  

此外,还应有足够的额外过载来确保:

     
      
  1. 如果对应double参数的任何算术参数的类型为long double,则所有算术参数对应于   double参数有效地转换为long double

  2.   
  3. 否则,如果对应于double参数的任何算术参数具有类型double或整数类型,则所有算术   对应于double参数的参数被有效地转换为   double

  4.   
  5. 否则,与double参数对应的所有算术参数都具有float类型。

  6.   

变量ul没有类型long double而是整数类型,所以我认为ul应该被转换为 double,然后ipart应为18446744073709551616。 (也就是说,GCC的行为是错误的。)

我对这种行为有误解吗? (当然,我认为海湾合作委员会的行为更为可取。)

1 个答案:

答案 0 :(得分:2)

你误解了这里发生的事情。

首先让我们通过将ul作为唯一参数传递给std::modf来检查#include <iostream> #include <iomanip> #include <climits> #include <cmath> int main() { unsigned long ul = ULONG_MAX; auto fpart = std::modf(ul, nullptr); std::cout << std::fixed << std::setprecision(0) << ul << ", " << ipart; } 将被投射到的内容:

prog.cc:9:46: error: call of overloaded 'modf(long unsigned int&, std::nullptr_t)' is ambiguous
...
/usr/local/gcc-head/include/c++/7.0.0/cmath:376:3: note: candidate: float std::modf(float, float*)
...
/usr/include/x86_64-linux-gnu/bits/mathcalls.h:116:1: note: candidate: double modf(double, double*)
...
/usr/local/gcc-head/include/c++/7.0.0/cmath:380:3: note: candidate: long double std::modf(long double, long double*)
...

无法编译:

long double ipart;

正如您所看到的,编译器无法确定要调用的3个重载函数中的哪一个,因为它不知道您传递的参数中的哪一个。

那你为什么要编译?

检查您传递的第二个参数:指向long double *的指针。 这就是编译器可以使用的东西。

是否有任何函数将long double modf( long double x, long double* iptr );作为第二个参数?是的,有:

#include <iostream> #include <iomanip> #include <climits> #include <cmath> int main() { unsigned long ul = ULONG_MAX; long double ipart; long double fpart = std::modf(static_cast<long double>(ul), &ipart); std::cout << std::fixed << std::setprecision(0) << ul << ", " << ipart << ", " << fpart << '\n' << static_cast<double>(ul) << '\n'; }

所以你的代码在这里做的或多或少是这样的:

static_cast<long double>(ul)

正如您现在所看到的那样,您正在将static_cast<double>(ul)new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION} 进行比较。