我发现gcc(4.9.2)和clang(3.5.0)之间的行为有所不同,令我感到惊讶.
当我尝试unsigned int
从一个std::istringstream
带有负值的初始值(在示例中为"-15")中提供一个时,我得到了
fail()
clang ++ 出错(带位)signed(-15)
用gcc ++ 初始化我准备了以下示例程序.
#include <sstream>
#include <iostream>
int main ()
{
std::istringstream iss("-15");
unsigned int ui;
iss >> ui;
std::cout << "ui[" << ui << "] signed(ui)[" << signed(ui)
<< "] flags[" << iss.fail() << iss.good() << iss.bad()
<< iss.eof() << "]\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用clang ++,我获得以下输出
ui[0] signed(ui)[0] flags[1001]
Run Code Online (Sandbox Code Playgroud)
使用g ++,我获得以下输出
ui[4294967281] signed(ui)[-15] flags[0001]
Run Code Online (Sandbox Code Playgroud)
我有两个问题.
首先是显而易见的:谁是对的?clang ++,g ++还是一个未定义的行为?
第二个是:我如何强制gcc ++的行为类似于clang ++,从一个以减号开头的字符串中提取无符号值时会出错?
谢谢,抱歉我的英语不好.
编辑2016.04.03
我意识到这不是g ++和clang ++之间的区别,而是libstd …
考虑这个程序:
#include <iostream>
#include <string>
#include <sstream>
#include <cassert>
int main()
{
std::istringstream stream( "-1" );
unsigned short n = 0;
stream >> n;
assert( stream.fail() && n == 0 );
std::cout << "can't convert -1 to unsigned short" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在OS X 10.5.6上的gcc(版本4.0.1 Apple Inc. build 5490)上试过这个,断言是真的; 它无法将-1转换为unsigned short.
但是,在Visual Studio 2005(和2008)中,断言失败,结果n的值与编译器生成的隐式转换的结果相同 - 即"-1"为65535," - 2"为65534等但随后在"-32769"变得奇怪,转换为32767.
谁是对的,谁在这里错了?(而且-32769到底发生了什么?)
我需要将一个宽字符串转换为双数字.据推测,字符串保持一个数字而没有别的(可能是一些空格).如果字符串包含其他内容,则应指出错误.所以我不能使用stringstream
- 如果字符串包含其他内容,它将提取一个数字而不指示错误.
wcstod
似乎是一个完美的解决方案,但它在Android上运行错误(GCC 4.8,NDK r9).我还可以尝试其他什么选择?