tags:

views:

84

answers:

2

I would like to know the rules specified by the C++ language standard for situations like:

long x = 200;
short y = static_cast<short>(x);

Is y guaranteed to be 200, or does the standard leave this up to the implementation to decide? How well do various compilers adhere to the standard?

+7  A: 

In this case the static_cast<> is an 'explicit type conversion. the standard has this to say about integral conversions in 4.7/3 "Integral conversions":

If the destination type is signed, the value is unchanged if it can be represented in the destination type (and bit-field width); otherwise, the value is implementation-defined.

Since short is guaranteed to be able to hold the value 200 (short must be at least 16 bits), then for your specific example the answer is yes.

Various compilers adhere to this behavior quite well - it's been that way since the pre-ANSI days of C, and so much code depends on the behavior that compiler vendors seem reluctant to even issue warnings about the possibility of truncation.

Michael Burr
A: 

If the value falls within the range of a short then the value is guaranteed to be correct, which in your case is true, so y == 200.

If it falls outside (e.g. static_cast<short>(1000000000)) then the behaviour is undefined. Most compilers will just truncate the binary digits down to the correct size.

Peter Alexander
Not undefined behavior, unspecified.
GMan
@GMan: not unspecified, but implementation-defined. There's a subtle difference - for implementation defined there's a specific behavior that the implementation needs to document, which is not necessary for unspecified behavior. The difference between 'unspecified' and 'undefined' behavior is that the there are generally a set of allowable behaviors for unspecified, while for undefined anything goes (including crashing).
Michael Burr
@Michael: Good to know, thanks.
GMan
@Michael:There's some room for argument over the limits on implementation defined behavior. In the C standard, the #pragma directive is defined as: "...causes the implementation to behave in an implementation-defined manner. The behavior might cause translation to fail or cause the translator or the resulting program to behave in a non-conforming manner." Two things are unclear: does this apply to "implementation-defined" in general, or just *this* I-D behavior? Does the same apply to C++, which doesn't include that wording, but doesn't say otherwise?
Jerry Coffin
@Jerry: the wording for that case is specific to that case. For instance, whether `char` is signed is also I.D., but using a plain `char` may not cause the implementation to fail (obviously). `#pragma` is unusually free in what it can do, by design. This includes causing translations to fail. `#pragma WarningsAsErrors` could do that, and that's not something the standard want to outlaw.
MSalters
@MSalters:I'm not sure it's so clear cut. I can't find a reference at the moment, but I'm quite certain I recall mention of this having been discussed by the committee, and there having been a fair number of committee members who did *not* consider it restricted to pragmas.
Jerry Coffin
@Jerry: it IS clearcut that there is no _general_ rule, as I;'ve given an example of an unrestricted case (`#pragma`) and of a restricted case (`char` sign, 2 options). That clarifies that the behavior can differ. I haven't enumerated and classified all cases of ID behavior, as these two examples are sufficient to show there's more than one rule.
MSalters