第 3 章 Programming: Principles and Practice using C++ (第六次打印),Stroustrup 指出(第 68 页):“请注意,sqrt()
不是为 int
定义的”.
下面是一个基于该章的简单 C++ 程序:
#include "std_lib_facilities.h"
int main()
{
int n = 3;
cout << "Square root of n == " << sqrt(n) << "\n";
}
鉴于上面的引用,我预计编译或运行该程序的过程会以某种方式失败。
令我惊讶的是,编译它(使用 g++ (GCC) 4.2.1)并成功运行,没有错误或警告,并产生了以下完美的输出:
Square root of n == 1.73205
因此我的问题是:如果 sqrt()
确实没有为 int
定义,那么为什么上面的程序不会以某种方式失败?
最佳答案
更新 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
部分数值库,然后转到 26.8
部分C 库 涵盖了 <cmath>
header ,它指定了 float、double 和 long double 的数学函数重载,这在 8 段中有介绍:
In addition to the double versions of the math functions in , C++ adds float and long double overloaded versions of these functions, with the same semantics.
这将是 ambiguous
对于 int
case 但标准要求提供足够的重载,以便将 integer 参数cast 为 double。它包含在 11 段中(强调我的):
Moreover, there shall be additional overloads sufficient to ensure:
- If any arithmetic argument corresponding to a double parameter has type long double, then all arithmetic arguments corresponding to double parameters are effectively cast to long double.
- Otherwise, if any arithmetic argument corresponding to a double parameter has type double or an integer type, then all arithmetic arguments corresponding to double parameters are effectively cast to double.
- Otherwise, all arithmetic arguments corresponding to double parameters have type float.
更新
正如@nos 指出的,sqrt
的版本可能被调用来自math.h
header 而不是来自 cmath
的重载,如果是这种情况,并且这里可能有一个实现定义警告,那么我们可能恢复到旧的C风格行为,如果唯一的版本可用的是 sqrt(double)
这意味着 int 将隐式转换为 double。
我找到了一种在 gcc
上测试它的方法和 clang
将对 a
使用 long 类型连同-Wconversion
如果我们只有 sqrt(double)
,标志会在我的平台上触发潜在值(value)改变转换的警告可用的。事实上,如果我包括 math.h
而不是 cmath
我们可以产生这个警告。虽然我无法在 clang 中触发此行为,这似乎表明这是依赖于实现。
关于c++ - 为什么 sqrt() 在没有为 int 定义的 int 变量上工作正常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19613191/