如果没有为int定义,为什么sqrt()在int变量上工作正常?

时间:2013-10-26 23:51:41

标签: c++ gcc g++ gcc4 gcc-4.2

Programming: Principles and Practice using C++ (第六次印刷)的第3章中,Stroustrup声明(第68页):“请注意sqrt()未定义为{{ 1}}“即可。

这是一个基于该章的简单C ++程序:

int

鉴于上面的引用,我预计编译或运行该程序的过程会以某种方式失败。

令我惊讶的是,编译它(使用g ++(GCC)4.2.1)并成功运行它没有错误或警告,并产生以下完美不错的输出:

#include "std_lib_facilities.h"

int main()
{
    int n = 3;
    cout << "Square root of n == " << sqrt(n) << "\n";
}

因此我的问题是:如果Square root of n == 1.73205 没有为sqrt()定义,那为什么上面的程序不会以某种方式失败?

6 个答案:

答案 0 :(得分:5)

10被隐式转换为双。只要您拥有正确的sqrt函数原型,就会自动执行此操作。

编辑:被评论打败

答案 1 :(得分:4)

更新2

这个问题与一个完全重复的内容合并,看看这个,实际答案比任何人原先想象的要简单得多。当前版本的std_lib_facilities.h包含以下行:

inline double sqrt(int x) { return sqrt(double(x)); }   // to match C++0x

int 创建一个特定的重载,以匹配现代编译器应该做的事情,将整数参数转换为double ,尽管此版本并未涵盖所有案件。

如果没有使用 std_lib_facilities.h 而原始逻辑仍然适用,尽管gcc-4.2与原始问题中的 Visual Studio 2012 相比较旧但是4.1.2版本专门针对整数情况使用__builtin_sqrt

原始

由于 2005 周围标准草案要求整数参数强制 double ,所以draft C++ standard。如果我们查看26 Numerics库部分,然后转到涵盖26.8标题的<cmath> C库部分,它会指定 float double long double 的数学函数的重载,其中包含 8

  

除了数学函数的双重版本之外,C ++还添加了这些函数的float和long double重载版本,具有相同的语义。

对于ambiguous情况int,但标准要求提供足够的重载,以便整数参数强制到< EM>双。它包含在 11 段中(强调我的):

  

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

     
    
        
  1. 如果对应于double参数的任何算术参数的类型为long double,则对应于double参数的所有算术参数都有效地转换为long double。
  2.     
  3. 否则,如果对应于double参数的任何算术参数具有double类型或整数类型,则则对应于double参数的所有算术参数将被有效地转换为double。
  4.     
  5. 否则,与double参数对应的所有算术参数都具有float。
  6. 类型        

更新

正如@nos所指出的那样,被调用的sqrt版本可能来自math.h标头而不是来自cmath的重载,如果是这种情况并且存在可能实现已定义警告此处,如果唯一可用的版本为sqrt(double),那么可能将恢复为旧的 C样式行为意味着 int 将被隐式转换为双重

我发现在gccclang上对此进行测试的一种方法是使用a long 类型以及-Wconversion标志如果我们只有sqrt(double)可用,则会在我的平台上触发可能会改变价值的警告。实际上,如果我包含math.h而不是cmath,我们就可以发出此警告。虽然我无法在 clang 中触发此行为,这似乎表明这是实现依赖

答案 2 :(得分:3)

由于隐式转化sqrt的定义为doubleint值可以隐式转换为类型double的值。

(实际上很难阻止使用double调用int的函数。您可能会让编译器发出警告,但由于这通常是一种保值转换,即使这可能很难.C ++继承了C设计尽可能努力使代码工作,即使它需要扭曲。其他语言对此类事情要严格得多。)

答案 3 :(得分:2)

sqrt是为double定义的。 C ++允许您隐式地将int转换为double

int n = 3;
double x = sqrt(n);    // implicit conversion of n from int to double

当您将值用作函数参数或将其指定给变量时,可能会发生隐式转换。

第二种情况的一个例子是:

int n = 3;
double x = n;          // implicit conversion of n from int to double

请注意,运算符也只是函数。因此,您还可以向int添加double,在调用实际添加内容之前将int转换为double

int n = 3;
double x = 1.0;
double sum = n + x;    // implicit conversion of n from int to double

答案 4 :(得分:1)

因为存在从intdouble的隐式转换。

通过转换,您的代码将如下所示:

cout << "Square root of n == " << sqrt((double)n) << "\n";

答案 5 :(得分:1)

因为编译器实际上是自动(即“隐式”)将整数转换为double(或者可能是long double)并将该值发送到sqrt()。这完全是正常和完全合法的。