当心,我说的是 :: abs(),而不是 std :: abs()
Beware, I am talking about ::abs(), not std::abs()
根据 cplusplus网站,<$对于 stdlib,c $ c> abs 的行为应有所不同。 h C版本,如果包含< cmath> ;
According to the cplusplus website, abs is supposed to behave differently for the stdlib.h C version, if you include <cmath>
这里是此页的摘录(处理 :: abs ,而不是 std :: abs ):
Here is an extract from the this page (which deals with ::abs, not std::abs):
double abs (double x); float abs (float x); long double abs (long double x); Compute absolute value /* Returns the absolute value of x: |x|. These convenience abs overloads are exclusive of C++. In C, abs is only declared in <cstdlib> (and operates on int values). The additional overloads are provided in this header (<cmath>) for the integral types: These overloads effectively cast x to a double before calculations (defined for T being any integral type). */真的吗?
在将程序移植到新平台时,由于不同的编译器和标准库的实现在这里有所不同,我对此颇为bit恼。
I have been bitten by this when porting a program to a new platform, since different compilers and standard libraries implementation differ here.
这是我的示例程序:
#include <iostream> //#include <stdlib.h>//Necessary inclusion compil under linux //You can include either cmath or math.h, the result is the same //#include <cmath> #include <math.h> int main(int argc, const char * argv[]) { double x = -1.5; double ax = std::abs(x); std::cout << "x=" << x << " ax=" << ax << std::endl; return 0; }这是MSVC 2010下的结果:
And here is the result under MSVC 2010:
- 在MSVC 2010下不会发出编译警告,即使您不包括math.h也不包含 stdlib.h :无论您做什么,似乎总是包含 math.h 和 stdlib.h
- 程序输出为: x = -1.5 ax = 1.5 (根据参考资料看似正确)
- No compilation warning is emitted under MSVC 2010, and the program will compile even if you do not include neither math.h nor stdlib.h: it seems like math.h and stdlib.h are always included whatever you do
- The program output is: x=-1.5 ax=1.5 (seemingly correct according to the reference)
现在这是OSX下的结果:
Now here is the result under OSX:
- 没有编译警告即使使用 -Wall 标志也不会发出(不指示对double进行强制转换)!如果将 g ++ 替换为 llvm-g ++ ,则结果相同。编译不需要包含 math.h 或 cmath 。
- 程序输出为: x = -1.5 ax = 1
- No compilation warning is emitted, even with the -Wall flag (the double to int cast is not signaled)! The result is the same if you replace g++ by llvm-g++. The inclusion of math.h or cmath is not required for the compilation.
- The program output is: x=-1.5 ax=1
最后是Linux下的结果:
And finally the result under Linux:
- 如果 stdlib.h 不包括在内(最后,一个不自动包含 stdlib 的编译器)。
- 程序输出为: x = -1.5 ax = 1
- The program will not compile if stdlib.h is not included (at last, one compiler that does not include stdlib automatically). No compilation warning is emitted for the double -> int cast.
- The program output is: x=-1.5 ax=1
这里没有明显的赢家。我知道一个明显的答案是首选 std :: abs 比 :: abs ,但是我想知道:
No clear winner here. I know that an obvious answer is "prefer std::abs to ::abs", but I wonder:
- 当cplusplus网站显示 abs 应该自动提供时,该网站是否位于此处 std 命名空间之外的双版本?
- 除了MSVC之外,所有编译器及其标准库在这里都出错了吗(尽管它包括 math.h 静默)?
- Is the cplusplus website right here when it says that abs should automatically provide double version outside of the std namespace?
- Are all compiler and their standard libraries wrong here except MSVC (although it includes math.h silently)?
官方参考资料说...很乱。 C ++ 11和C11之前的版本:
The official references say... it's a mess. Pre-C++11 and C11:
-
正式包括< cmath> 在 :: 中什么也没有引入; 所有功能都在 std :: 中。实际上,只有 export 受到较少的尊重,并且不同的编译器所做的所做的事情非常不同。如果您包含< cmath> ,则在各处使用 std :: ,或者您得到的变化从编译器到编译器。
Officially, including <cmath> introduced nothing in ::; all of the functions were in std::. Practically, only export was less respected, and different compilers did very different things. If you included <cmath>, you used std:: everywhere, or what you got varied from compiler to compiler.
C没有提供任何重载: abs 占用了 int ,并且是在< stdlib.h> , fabs 拿了双,并且是在< math.h> 中声明的。
C didn't provide any overloads: abs took an int, and was declared in <stdlib.h>, fabs took double, and was declared in <math.h>.
如果在C ++中包含< math.h> ,则不清楚是什么得到了,但是由于实施者似乎都不在乎标准中的(请参见上面的第一点)...
If you included <math.h> in C++, it's not clear what you got, but since none of the implementers seemed to care about the standard anyway (see the first point above)...
粗略地说,您包括了< cmath> ,并在所有的前缀前加上了 std :: ,或者您包含了< math.h> ,而使用了 fabs 如果您想支持浮点(以及除 int 或 double 以外的类型的各种后缀) )。
Roughly speaking, either you included <cmath>, and prefixed all of the uses with std::, or you included <math.h>, and used fabs if you wanted support for floating point (and the various suffixes for types other than int or double).
C ++ 11和C11增加了一些新的变化:
C++11 and C11 added a few new twists:
-
< cmath>
<cmath> is now allowed (but not required) to introduce the symbols in :: as well. One more thing which can vary depending on the implementation. (The goal here was to make existing implementations conformant.)
C具有新的标头< tgmath。 h> ,它使用编译器魔术来使使< math.h> 中的函数的行为就像它们是如C ++中那样重载。 (因此,它不适用于 abs ,但是只有到 fabs 。)此标头具有 not 已添加到C ++中,这是因为的明显原因是C ++不需要的任何编译器魔术。
C has a new header, <tgmath.h>, which uses compiler magic to make the functions in <math.h> behave as if they were overloaded as in C++. (So it doesn't apply to abs, but only to fabs.) This header had not been added to C++, for the obvious reason that C++ doesn't need any compiler magic for this.
总而言之,情况略有恶化,我上面的建议仍然成立。包括< math.h> 和 < stdlib.h> 并使用 abs / fabs 及其派生产品(例如 labs , fabsf 等),或包含< cmath> ,而使用 std :: abs 。还有其他事情,您会遇到可移植性问题。
All in all, the situation has become slightly worse, and my recommendations above still hold. Include either <math.h> and <stdlib.h>, and use abs/fabs and their derivated (e.g. labs, fabsf, etc.) exclusively, or include <cmath>, and use std::abs exclusively. Anything else, and you'll run into portabiity problems.
更多推荐
abs vs std :: abs,参考文献怎么说?
发布评论