Question

I'm reading a Stroustrup's book "The C++ Programming Language 4th edition" and have three questions regarding overflowing assignments (particularily to signed/unsigned chars, as the book exemplifies). Firstly, according to standard 5/4 paragraph:

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

(Except when a destination variable is unsigned - the result is clearly defined in such case). But does this definition also pertain to assignments?

Because in my opinion there are many contrary statements in the book, all in chapter 6. The first one corresponds to the aforementioned paragraph, however the following comments doesn't:

Variables of the three char types can be freely assigned to each other. However, assigning a too large value to a signed char is still undefined. For example:

void g(char c, signed char sc, unsigned char uc)
{
    c = 255; //implementation-defined if plain chars are signed and have 8 bits
    c = sc; //OK
    c = uc; //implementation-defined if plain chars are signed and if uc's value is too large
    sc = uc; //implementation-defined if uc's value is too large
    uc = sc; //OK: conversion to unsigned
    sc = c; //implementation-defined if plain chars are unsigned and if c's value is too large
    uc = c; //OK: conversion to unsigned
}

First question: since assigning a too large value is UB, then why comments say it's implementation-defined?

Next we have the following example:

To be concrete, assume that a char is 8 bits:

signed char sc = -160;
unsigned char uc = sc; //uc == 116 (because 256-160==116)
cout << uc; //print 't'

Second question: apart from the fact that the first assignment is supposedly UB, what formula exactly has the author used in order to come up with 116? In my test, uc got the value of 96.

And the last quote:

An integer can be converted to another integer type. If the destination is signed, the value is unchanged if it can be represented in the destination type; otherwise, the value is implementation-defined:

signed char sc = 1023; //implementation-defined

Plausible results are 127 and -1.

Third question: again, apart from the fact that this contrary to what have been said earlier about UB, why possible results are 127 and -1? I guess it has something to do with one's and two's complement, but what are the precise formulas used?

Was it helpful?

Solution

1) Implementation defined is "a class of UB" - in other words, it's still UB, it's just that the implementation is responsible for explaining how it works, rather than "you can't at all rely on this operation". So, the compiler is still allowed to explode your computer if you assign out-of-range char values. But the implementation can also define that "it chops it to the 8-bit equivalent value".

2) 256 - 160 = 96 on my calculator. I bet it is on yours as well. Maybe the author had a different calculator? Or it's one of those things that got changed last minute from -150 to -160, it forgot to change the end result.

3) Since it's "implementation defined", it could end up being almost anything. Since the value is 0x3ff in hex, we can imagine either 0xff or 0x7f as plausible values, depending on how the implementation decides to do that. I expect MOST compilers will use the 0xff value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top