Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unusual behavior of standard library function abs() on different C++ compilers

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.

like image 847
Destructor Avatar asked Sep 20 '25 08:09

Destructor


1 Answers

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.

like image 77
StoryTeller - Unslander Monica Avatar answered Sep 22 '25 00:09

StoryTeller - Unslander Monica