On 21/12/2022 06:31, Andrey Tarasevich wrote:
> On 12/20/2022 12:46 PM, Andrey Tarasevich wrote:
>> On 12/18/2022 12:00 PM, Roman P wrote:
>>
>>> 3) What happens when you overflow an int variable, that is, set it to a
>>> value beyond its range?
>>
>> "Set"? What does "set" mean in this context?
>>
>> Behavior of variables in out-of-range situations depends critically on
>> _how_ you attempt to produce an out-of-range value in it. For example,
>> assignment is one thing, while side effect of `++` is a completely
>> different thing.
>>
>
> ... although here I'm probably trying to be too smart for my own good:
I think we are all trying to be "smart" here - whether we are being
/too/ smart is an open question!
> there's no need for this kind of branching. In the end, side effects
> modify the variable value through assignment as well.
>
> This means that trying to "set an int to a value beyond its range"
> results in a congruent value in C++ and in an implementation-defined
> value or a signal in C. Overflow-related undefined behaviors that can
> still occur in signed integer arithmetic are not relevant to this
> question, since they are not really related to "setting" a variable value.
>
> One can still note though that trying to set an int variable to an
> overly large floating-point value results in UB. Although even here one
> can argue that the UB occurs as part of the conversion, which happens
> before the actual "setting".
>
I think there are three things to consider here. First, there is the
issue of what the OP meant. Then there are the two different ways to
set the value of a variable.
Regarding the OP's intention - while this is speculation, I believe he
was thinking of signed integer overflow in arithmetic expressions -
overflow in the addition part of "x = a + b;" rather than in the
assignment part. And in that case, signed integer overflow is undefined
behaviour in C and C++, and many compilers optimise on the assumption
that it never happens. (A few compilers, like "gcc -fwrapv", give it
defined behaviour.)
Setting a variable explicitly (whether it be by initialisation,
assignment, augmented assignment, or increment/decrement operator
side-effects) is a matter of conversion. For an integer type to an int,
this is covered in 6.3.1.3. If the value to be converted cannot be
represented in the new type (int, in this case), "either the
result is implementation-defined or an implementation-defined signal is
raised." For almost all compilers, excluding sanitizers or special
debug modes, this is done by two's complement wrapping.
Conversion from a floating point number that is out of range is
undefined behaviour.
The other way to change a variable is using memcpy, a character pointer,
or a union. These methods affect the underlying representation
directly, and do not operate on values - so "overflow" or "range" makes
no sense. You can get undefined behaviour later when the value is read,
if it is a trap or otherwise does not represent a valid value of the
type. (You won't see that with integers, in real-world compilers - but
you can see it if you set a _Bool variable to something other than 0 or
1 using memcpy() or a char pointer.)