Quote:
Originally Posted by Zaccheus
SuperKoko, why is type conversion significant to the wrapping behaviour of ++ in this context?
++ test.s is equivalent to test.s+=1
Quote:
Originally Posted by C99
The value of the operand of the prefix ++ operator is incremented. The result is the new
value of the operand after incrementation. The expression ++E is equivalent to (E+=1).
See the discussions of additive operators and compound assignment for information on
constraints, types, side effects, and conversions and the effects of operations on pointers.
test.s+=1 is equivalent to test.s=test.s+1
Quote:
3 Acompound assignment of the form E1 op =E2differs from the simple assignment
expression E1 = E1 op (E2) only in that the lvalue E1 is evaluated only once.
This bit-field lvalue test.s has a type... And this type is an integer type on its own, different from all other integer types. This type is described.
Quote:
A bit-field is interpreted as a signed or unsigned integer type consisting of the specified
number of bits.105) If the value 0 or 1 is stored into a nonzero-width bit-field of type
_Bool, the value of the bit-field shall compare equal to the value stored.
It might worth looking at integer representations specification (even though this isn't the matter of this post):
Quote:
The representations of all types are unspecified except as stated in this subclause.
2 Except for bit-fields, objects are composed of contiguous sequences of one or more bytes,
the number, order, and encoding of which are either explicitly specified or
implementation-defined.
3 Values stored in unsigned bit-fields and objects of type unsigned char shall be
represented using a pure binary notation.40)
...
40) A positional representation for integers that uses the binary digits 0 and 1, in which the values
represented by successive bits are additive, begin with 1, and are multiplied by successive integral
powers of 2, except perhaps the bit with the highest position. (Adapted from the American National
Dictionary for Information Processing Systems.) A byte contains CHAR_BIT bits, and the values of
type unsigned char range from 0 to 2 CHAR_BIT
-1.
The lvalue test.s whose type is a bit-field type appears as an operand to an arithmetic operator, so, integer promotion occurs:
Quote:
2 The following may be used in an expression wherever an int or unsigned int may
be used:
— An object or expression with an integer type whose integer conversion rank is less
than or equal to the rank of int and unsigned int.
— A bit-field of type _Bool, int, signed int,orunsigned int.
If an int can represent all values of the original type, the value is converted to an int;
otherwise, it is converted to an unsigned int. These are called the integer
promotions.48) All other types are unchanged by the integer promotions.
And, it yields an int, the conversion being value-preserving.
Then, 1 is added and the resulting int is converted back to the bit-field type on the left side of the assignment operator because:
Quote:
In simple assignment (=), the value of the right operand is converted to the type of the
assignment expression and replaces the value stored in the object designated by the left
operand.
Then, reading the rules of integer conversions (since int is an integer type and the bit-field type is an integer type too):
Quote:
1 When a value with integer type is converted to another integer type other than _Bool,if
the value can be represented by the new type, it is unchanged.
2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or
subtracting one more than the maximum value that can be represented in the new type
until the value is in the range of the new type.49)
3 Otherwise, the new type is signed and the value cannot be represented in it; either the
result is implementation-defined or an implementation-defined signal is raised.
If the value can be represented in the bit-field, it's preserved, otherwise, point (2) is applied:
For example if test.s==3, test.s+1==4 and this value is converted to 0 by substracting 4 (well, this is a simple reduction modulo 4).
C++ has similar wording:
Promotion:
Quote:
Originally Posted by C++
4.5 Integral promotions [conv.prom]
3 An rvalue for an integral bit-field (_class.bit_) can be converted to
an rvalue of type int if int can represent all the values of the bit-
field; otherwise, it can be converted to unsigned int if unsigned int
can represent all the values of the bit-field. If the bit-field is
larger yet, no integral promotion applies to it. If the bit-field has
an enumerated type, it is treated as any other value of that type for
promotion purposes.
Quote:
Originally Posted by C++
4.7 Integral conversions [conv.integral]
1 An rvalue of an integer type can be converted to an rvalue of another
integer type. An rvalue of an enumeration type can be converted to an
rvalue of an integer type.
2 If the destination type is unsigned, the resulting value is the least
unsigned integer congruent to the source integer (modulo 2n where n is
the number of bits used to represent the unsigned type). [Note: In a
two's complement representation, this conversion is conceptual and
there is no change in the bit pattern (if there is no truncation). ]
3 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.
4 If the destination type is bool, see _conv.bool_. If the source type
is bool, the value false is converted to zero and the value true is
converted to one.
5 The conversions allowed as integral promotions are excluded from the
set of integral conversions.