Consider following program:
#include <cstdio>
#include <cmath>
int main()
{
int d = (int)(abs(0.6) + 0.5);
printf("%d", d);
return 0;
}
g++
7.2.0 Output 0 ( See live demo here )
g++
6.3.0 ( See live demo here )
prog.cc: In function 'int main()':
prog.cc:6:26: error: 'abs' was not declared in this scope
int d = (int)(abs(0.6) + 0.5);
^
prog.cc:6:26: note: suggested alternative:
In file included from prog.cc:2:0:
/opt/wandbox/gcc-6.3.0/include/c++/6.3.0/cmath:103:5: note: 'std::abs'
abs(_Tp __x)
^~~
clang++
5.0.0 Output 1 ( See live demo here )
clang++
3.6.0 ( See live demo here )
prog.cc:6:19: error: use of undeclared identifier 'abs'; did you mean 'fabs'?
int d = (int)(abs(0.6) + 0.5);
^~~
fabs
/usr/include/x86_64-linux-gnu/bits/mathcalls.h:181:14: note: 'fabs' declared here
__MATHCALLX (fabs,, (_Mdouble_ __x), (__const__));
^
/usr/include/math.h:71:26: note: expanded from macro '__MATHCALLX'
__MATHDECLX (_Mdouble_,function,suffix, args, attrib)
^
/usr/include/math.h:73:22: note: expanded from macro '__MATHDECLX'
__MATHDECL_1(type, function,suffix, args) __attribute__ (attrib); \
^
/usr/include/math.h:76:31: note: expanded from macro '__MATHDECL_1'
extern type __MATH_PRECNAME(function,suffix) args __THROW
^
/usr/include/math.h:79:42: note: expanded from macro '__MATH_PRECNAME'
#define __MATH_PRECNAME(name,r) __CONCAT(name,r)
^
/usr/include/x86_64-linux-gnu/sys/cdefs.h:88:23: note: expanded from macro '__CONCAT'
#define __CONCAT(x,y) x ## y
^
1 error generated.
Microsoft VC++ 19.00.23506 Output 1 ( See live demo here )
What exactly is happening here in this program ? Why it gives different output when compiled on different C++ compilers ? Why program exhibits different behavior even on different version of same compiler ? Is this compiler issue or standard library (libstdc++
& libc++
) issue ? What C++ standard says about this ?
P.S: I know that I need to write std::abs
instead of abs
. But this is not my question.
All the cname
library headers that bring in functionality from the C standard library must introduce those symbols in namespace std
. They also may, but definitely not must introduce them into the global namesapce. [headers]/4:
Except as noted in Clauses [library] through [thread] and Annex [depr], the contents of each header cname is the same as that of the corresponding header name.h as specified in the C standard library. In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope of the namespace std. It is unspecified whether these names (including any overloads added in Clauses [language.support] through [thread] and Annex [depr]) are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations.
So different compilers, and even different compiler versions, mean different implementation details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With