Submitter: UK C Panel
Submission Date: 2005-03-04
Source: Joseph Myers <joseph@codesourcery.com>
Reference Document: ISO/IEC
WG14 N1103
Version: 1.5
Date: 2007-10-10
Subject: Implementation-defined bit-field types
Summary
C99 6.7.2#2 lists the valid combinations of type specifiers. 6.7.2#5 says:
[#5] Each of the comma-separated sets designates the same type, except that for bit-fields, it is implementation-defined whether the specifierint
designates the same type assigned int
or the same type asunsigned int
.
6.7.2.1#4 says:
[#4] A bit-field shall have a type that is a qualified or unqualified version of_Bool
,signed int
,unsigned int
, or some other implementation-defined type.
Some problems arise with use of an "other implementation-defined type", a new addition in C99.
1. Suppose an implementation supports bit-fields of types
char
, short
, long
and
long long
. Bit-fields of type int
may
be unsigned on that implementation. Must bit-fields of type
char
nevertheless have the same signedness as
ordinary objects of type char
, and similarly for
those of types short
(or short int
),
long
(or long int
), long
long
(or long long int
)? The practice in C++
is that all these are implementation-defined (except that C++
does not include long long
); it seems an oversight
in the addition of implementation-defined bit-field types in C99
not to make such provision for char
,
short
, long
and long long
bit-fields as is made for int
bit-fields. (It might
still be appropriate to ensure, for example, that
short
and short int
have the same
signedness as bit-field types, although that might be unsigned
and so differ from the signedness of signed short
and signed short int
.) Footnote 104, reiterating
that int
as a bit-field type may be signed or
unsigned, would also need amendment.
2. Suppose an implementation has 32-bit int
(with
no padding bits) and permits unsigned long long
as
an implementation-defined bit-field type. Consider the code:
struct s { unsigned long long a : 37, b : 37; } x; // ... sizeof(x.a + x.b);
x.a
and x.b
have 37-bit unsigned
integer types, by 6.7.2.1#9. Such types have an integer
conversion rank greater than that of int
, so are
unchanged by the integer promotions. (That all the bit-field
types have integer conversion ranks, and may need to be
documented by implementations as extended integer types, is a
consequence of the standard that may not be intended and may be
surprising to some, but it is a logical consequence of the text
of the standard.) Whether or not x.a
and
x.b
have the same 37-bit type, (x.a +
x.b)
also has a 37-bit unsigned integer type. However,
(x.a + x.b)
does not designate a bit-field member,
so it does not violate the constraints on sizeof
.
But what should sizeof(x.a + x.b)
evaluate to, when
(x.a + x.b)
has such a bit-field type which does not
occupy an integer number of bytes? Must an implementation define
representations occupying an integer number of bytes (with some
padding bits) for all such types, although such representations
would have no use other than to define the result of
sizeof
?
Changing the promotion rules for bit-fields wider than int to
avoid such expressions of bit-field type would create an odd
inconsistency in the type system about which types are promoted,
although it would be consistent with C++ where bit-fields have
narrow representation but are considered to have the declared
type rather than a special narrow type and would allow
implementations to support bit-fields wider than int
without needing special support for arithmetic on such types
(alternatively, it could be argued that if an implementor wishes
to support bit-fields wider than int
it is up to
them to implement arithmetic on all bit-field types wider than
int
as a consequence of their decision); changing
the C definition of bit-field types to follow the C++ one would
be more radical and probably not suitable for a TC. (C++ then has
a special rule so that unsigned int
bit-fields
promote to int
if narrower than int
.)
The alternative is to be more explicit about the nature of
bit-field types and to define when an expression has such a type,
and to make the constraint on sizeof
apply to
expressions with such types and not just to bit-fields
themselves.
Suggested Technical Corrigendum
Committee Discussion (for history only)
This defect report has been move back to open, to liaison with C++ - 2005-09-28
The Committee decision was to withdraw the answers to 2 and 3, see 6.3.1.1;p2.
Question 1: Must bit-fields of type char nevertheless have the same signedness as ordinary objects of type char, and similarly for those of types short (or short int), long (or long int), long long (or long long int)?
This is unspecified in the Standard - No.
Question 2: But what should sizeof(int) evaluate to, when (x.a + x.b) has such a bit-field type which does not occupy an integer number of bytes?
It must be something larger than int.
Question 3: Must an implementation define representations occupying an integer number of bytes (with some padding bits) for all such types, although such representations would have no use other than to define the result of sizeof?
Yes.
Consider this relevant citation:
6.3.1.1 Boolean, characters, and integers
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
, or
unsigned int
.
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. 48) The integer promotions are applied only:
as part of the usual arithmetic conversions, to certain argument
expressions, to the operands of the unary +
,
-
, and ~
operators, and
to both operands of the shift operators, as specified by their
respective subclauses.
This citation supports the committee's view that the type of a
bit-field does not include the width; if
int:7
were a type that is different from
int
, then these rules would not apply to any
bit-field type, an obviously incorrect conclusion.
Question 1: Must bit-fields of type char nevertheless
have the same signedness as ordinary objects of type
char
, and similarly for those of types
short
(or short int
),
long
(or long int
),
long long
(or long long
int
)?
These are all determined by the implementation-defined behavior specified in 6.7.2.1#4.
Question 2: But what should sizeof(x.a +
x.b)
evaluate to, when (x.a + x.b)
has such a bit-field type which does not occupy an integer number
of bytes?
In the example presented above, the type isunsigned long long
, and it does occupy an integral number of bytes. The expression evaluates tosizeof(unsigned long long)
.
Note: | This DR was marked to move into Review status after the Spring 2006 meeting. However, the document voted on at the Spring 2006 meeting had no Proposed text only Discussion text. The Editor decided to leave the DR as Open and allow the Committee to decide on the Proposed text for this DR at the Fall 2006 meeting. |
Question 1: Must bit-fields of type
char
nevertheless have the same signedness as
ordinary objects of the char
, and similarly
for those of types short
(or short
int
), long
(or long
int
), long long
(or long
long int
)?
these would all be implementation-defined, determined by the implementation-defined behavior specified in 6.7.2.1#4.
Question 2: But what should sizeof(x.a +
x.b)
evaluate to, when (x.a +
x.b)
has such a bit-field type which does not occupy an
integer number of bytes?
In example presented above, this would be implementation-defined, determined by the implementation-defined behavior specified in 6.7.2.1#4.
Proposed Technical Corrigendum
Last sentence of paragraph 2 of 6.3.1.1, add the words as restricted by the width, for a bit-field as follows:
If anint
can represent all values of the original type (as restricted by the width, for a bit-field), the type is converted to anint
;
Previous Defect Report < - > Next Defect Report