Re: What is the correct behaviour?
Seungbeom Kim wrote:
Alberto Ganesh Barbati wrote:
James Kanze ha scritto:
Jonne Lehtinen wrote:
std::string a( "-432" );
unsigned long b = 0;
std::stringstream stream;
if( !(stream << a && stream >> b) ) {
// Should fail?
}
It's undefined behavior, but from a quality of implementation
point of view, I would expect failure. You have the value -432,
which isn't representable in an unsigned long.
I can't see what makes the behaviour undefined. Could you please
elaborate? What would be necessary to make the behavior of that code
defined?
27.6.1.2.2 [lib.istream.formatted.arithmetic] defers the behaviour to
22.2.2.1 [lib.locale.num.get], which defers the behaviour to scanf (with
the conversion specifier "%lu" in this case), and the C standard states:
"If this object does not have an appropriate type, or if the result of
the conversion cannot be represented in the object, the behavior is
undefined."(7.9.6.2/10 in C90, 7.19.6.2/10 in C99).
That's exactly the passages I was thinking of. In the special
case of conversion to unsigned long, however, we have to
consider that the "conversion" of the text string is deferred to
stdtoul, and stdtoul does define a result when a minus sign is
present. A result which, by definition, can be represented in
an unsigned long. So I'm no longer sure that this particular
example is undefined behavior, although the problem exists in
general. (And the defined behavior is, in fact,
counter-intuitive, and not what I would want.)
Yes, it does sound harsh -- then how could we write a program that
behaves only in defined ways in response to arbitrary inputs? Extra
checking before calling scanf() or operator>>() (which isn't always
feasible)?
I think in general, you have to count a little bit on quality of
implementation, and refuse to use libraries which don't have
correct error handling. If we exclude the special case of an
explicitly negative value being assigned to an unsigned (because
of the above considerations), all of the libraries I have access
to except the STL port detect overflow correctly, setting
failbit. For unsigned, both the standard Sun CC library (Rogue
Wave, I think) and g++ reject negative numbers, VC++
(Dinkumware) seems to interpret the above statements concerning
the behavior of strtoul literally, and accepts them, with the
same results as if the results were ULONG_MAX + 1 - value (but
it is still inconsistent in that it doesn't signal an error if I
input -32768 into an unsigned short. (The results of strtoul
for this string are defined to be 4294934528 on my machines, and
this value isn't representable in an unsigned short.)
And even STL port doesn't do anything worse than returning a
fantasy value with no error---I'm pretty sure that it won't
reformat your hard disk.
But yes, it would be nice if all implementations agreed as to
what the desired behavior was, regarding negative values read
into an unsigned. (The behavior of Dinkumware can only be
intentional---I can't imagine a programming error allowing
-32768 to be read into an unsigned short, but signaling an error
for 65536.) And it would be even nicer if the standard
specified it black on white.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]