当心,我在说::abs(),不是std::abs()
根据cplusplus.com网站,abs对于stdlib.h C版本应该表现不同,如果你包括<cmath>
以下是此页面的摘录(::abs不处理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 …Run Code Online (Sandbox Code Playgroud) 考虑以下(错误)C++代码:
#include <cmath>
#include <cstdlib>
#include <iostream>
int main() {
if (abs(-0.75) != 0.75) {
std::cout << "Math is broken!\n";
return 1;
} else {
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码是错误的,因为它调用abs(含义::abs)而不是std::abs.取决于实现,::abs可能不存在,或者它可能是C abs,或者它可能是包含版本的重载集double,如std::absis.
在Linux上使用Clang,至少在我的环境中,它被证明是第二种选择:C abs.这引发了两个警告,即使没有明确启用任何警告:
<source>:7:9: warning: using integer absolute value function 'abs' when argument is of floating point type [-Wabsolute-value]
if (abs(-0.75) != 0.75) {
^
<source>:7:9: note: use function 'std::abs' instead
if (abs(-0.75) != 0.75) { …Run Code Online (Sandbox Code Playgroud) 即将推出的C++ 0x标准的最终委员会草案说:
每个C头(每个头都具有name.h形式的名称)的行为就好像每个由相应的cname头放置在标准库命名空间中的名称放在全局命名空间范围内.未指定是在名称空间std的名称空间作用域(3.3.6)中首先声明或定义这些名称,然后通过显式使用声明(7.3.3)将这些名称注入到全局名称空间作用域中.
早期的C++标准读起来类似.
我的问题是,当C++标头#include<cname>使用重载函数时,都会引入所有重载#include<name.h>,因为重载不是单独的"名称"?
以下代码的行为应该在符合标准的C和C++编译器之间有所不同吗?
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(void)
{
double arg = -2.5;
double result = abs(arg) / 3;
printf("%f\n", result);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译就绪测试用例:
math.h和stdlib.h:http://ideone.com/pmD4tmath.h和stdlib.h:http://ideone.com/Sflpncmath和cstdlib:http://ideone.com/yI07mcmath仅限C++ :http://ideone.com/KrS3W从这个测试来看,C++ math.h就像C一样,而不像C++ cmath.
但在Visual C++ 2010上,C++ math.h就像C++一样cmath.
和Comeau试用的编译时金丝雀:
#include<stdio.h>
#include<stdlib.h>
#include<math.h> …Run Code Online (Sandbox Code Playgroud)