问题
Beware, I am talking about ::abs(), not std::abs()
According to the cplusplus.com website, abs is supposed to behave differently for the stdlib.h C version, if you include <cmath>
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).
*/
Really???
I have been bitten by this when porting a program to a new platform, since different compilers and standard libraries implementation differ here.
Here is my sample program:
#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;
}
And here is the result under MSVC 2010:
- 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 likemath.handstdlib.hare always included whatever you do - The program output is:
x=-1.5 ax=1.5(seemingly correct according to the reference)
Now here is the result under OSX:
- No compilation warning is emitted, even with the
-Wallflag (the double to int cast is not signaled)! The result is the same if you replaceg++byllvm-g++. The inclusion ofmath.horcmathis not required for the compilation. - The program output is:
x=-1.5 ax=1
And finally the result under Linux:
- The program will not compile if
stdlib.his not included (at last, one compiler that does not includestdlibautomatically). No compilation warning is emitted for the double -> int cast. - The program output is:
x=-1.5 ax=1
No clear winner here. I know that an obvious answer is "prefer std::abs to ::abs", but I wonder:
- Is the cplusplus.com website right here when it says that
absshould automatically provide double version outside of thestdnamespace? - Are all compiler and their standard libraries wrong here except MSVC (although it includes
math.hsilently)?
回答1:
The official references say... it's a mess. Pre-C++11 and C11:
Officially, including
<cmath>introduced nothing in::; all of the functions were instd::. Practically, onlyexportwas less respected, and different compilers did very different things. If you included<cmath>, you usedstd::everywhere, or what you got varied from compiler to compiler.C didn't provide any overloads:
abstook anint, and was declared in<stdlib.h>,fabstookdouble, and was declared in<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)...
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 and C11 added a few new twists:
<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 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 toabs, but only tofabs.) This header had not been added to C++, for the obvious reason that C++ doesn't need any compiler magic for this.
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.
来源:https://stackoverflow.com/questions/21392627/abs-vs-stdabs-what-does-the-reference-say