c++ - 为什么 sqrt() 在没有为 int 定义的 int 变量上工作正常?

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

第 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 ,它指定了 floatdoublelong 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 参数castdouble。它包含在 11 段中(强调我的):

Moreover, there shall be additional overloads sufficient to ensure:

  1. 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.
  2. 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.
  3. 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/

相关文章:

c++ - 使用 boost::mpl 的类型组合

android - 在CCTools Android中编译两个文件(已安装GCC Addon)

c++ - Makefile 不评估 OBJECTS 变量

optimization - 如何减少或消除 __tls_init 调用?

c++ - gdb 在 Windows 中无法正常工作

c++ - 类成员初始化的最佳实践

c++ - 如何在模板中使用结构体作为参数 c++

c++ - 如何让 GDB 显示每行输出的时间戳?

c - 它在 GCC 源代码的哪个位置编译成不同的汇编语言?

使用 gcc-4.9 将矢量化检查为简单示例