stringstream unsigned conversion broken?

…衆ロ難τιáo~ 提交于 2019-12-01 19:18:16

The behaviour claimed by GCC in Max Lybbert's post is based on the tables om the C++ Standard that map iostream behaviour onto printf/scanf converters (or at least that;'s my reading). However, the scanf behaviour of g++ seems to be different from the istream behavior:

#include <iostream>
#include <cstdio>
using namespace std;;

int main()
{
    unsigned short n = 0;
    if ( ! sscanf( "-1", "%hu", &n ) ) {
        cout << "conversion failed\n";
    }
    else {
        cout << n << endl;
    }
}

actually prints 65535.

First, reading the string "-1" as a negative number is locale dependent (it would be possible for a locale to identify negative numbers by enclosing them in parenthesis). Your default standard is the "classic" C locale:

By far the dominant use of locales is implicitly, in stream I/O. Each istream and ostream has its own locale. The locale of a stream is by default the global locale at the time of the stream’s creation (page 6). ...

Initially, the global locale is the standard C locale, locale::classic() (page 11).

According to the GCC guys, numeric overflow is allowed to fail the stream input operation (talking about negative numbers that overflowed a signed int):

[T]he behaviour of libstdc++-v3 is strictly standard conforming. ... When the read is attempted it does not fit in a signed int i, and it fails.

Thanks to another answer, a bug was filed and this behavior changed:

Oops, apparently we never parsed correctly negative values for unsigned. The fix is simple. ...

Fixed in mainline, will be fixed in 4.4.1 too.

Second, although integer overflow is generally predictable, I believe it's officially undefined behavior, so while I can't say why -32769" converts to 32767, I think it's allowed.

Try this code:

#include <iostream>
#include <string>
#include <sstream>
#include <cassert>

int main()
{
    std::istringstream stream( "-1" );
    std::cout << "flags: " << (unsigned long)stream.flags() << std::endl;
    return 0;
}

I tried this on my VS2005:

flags: 513

and on codepad.org (which I think uses g++) this gives:

flags: 4098

This tells me that gcc uses a different default fmtflags. Since fmtflags control what conversions are possible you are getting different results.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!