繁体   English   中英

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

[英]Why does sqrt() work fine on an int variable if it is not defined for an int?

在《 编程:使用C ++的原理和实践》 (第六次印刷)的第3章中,Stroustrup指出(第68页): “请注意,没有为int定义sqrt()

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

#include "std_lib_facilities.h"

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

鉴于以上引用,我希望编译或运行该程序的过程会在某种程度上失败。

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

Square root of n == 1.73205

因此,我的问题是:如果sqrt()确实没有为int定义,那么上面的程序为什么不以某种方式失败?

10正在隐式转换为double。 只要您具有sqrt的正确函数原型,此操作就会自动发生。

编辑:被评论打败

更新2

将这个问题与一个完全重复的问题合并在一起,看看这个问题,实际答案比任何人最初想的都要简单得多。 当前版本的std_lib_facilities.h包含以下行:

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

这会为int情况创建一个特定的重载,以匹配现代编译器应做的工作,即将整数参数转换为double ,尽管此版本未涵盖所有情况。

如果未使用std_lib_facilities.h ,则原始逻辑仍然适用,尽管从原始问题来看,与Visual Studio 2012相比, gcc-4.2已经相当老了,但是4.1.2版本使用__builtin_sqrt专门用于整数情况。

原版的

2005年左右开始 ,标准草案要求将整数参数强制转换两倍,这在C ++标准草案中已涉及。 如果我们看一下第26 ,然后转到第26.8C库 ,它覆盖了<cmath>标头,它指定了floatdoublelong double的数学函数的重载,这在第8段中进行了介绍:

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

这将是ambiguousint情况,但该标准要求的是,提供足够的过载,使得整数参数被转换加倍 它在第11段中涉及( 强调我的 ):

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

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

更新资料

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

我发现在gccclang对此进行测试的一种方法是将long类型用于a ,如果我们只有sqrt(double)可用,它与-Wconversion标志一起触发在我的平台上可能更改值的警告。 的确,如果我包括math.h而不是cmath我们可以产生此警告。 尽管我无法在clang中触发此行为,但这似乎表明这与实现有关

由于隐式转换 sqrt是为double定义的,并且可以将int值隐式转换为double类型的值。

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

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

注意,运算符也只是函数。 因此,您还可以在double添加一个int ,从而在调用实际的加法之前将int转换为double

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

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

进行转换后,您的代码将如下所示:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM