I can't find anywhere in the C standard where this is specified. For example, in
struct { signed int x:1; } foo;
is foo.x
an lvalue of type int
, or something else? It seems unnatural for it to be an lvalue of type int
since you cannot store any value of type int
in it, only 0 or -1, but I can't find any language that would assign it a different type. Of course, used in most expressions, it would get promoted to int
anyway, but the actual type makes a difference in C11 with _Generic
, and I can't find any language in the standard about how bitfields interact with _Generic
either.
The type of a bit-field is:
bit-field of type
T
where
T
is either_Bool
,int
,signed int
,unsigned int
or some implementation-defined type.In your example,
foo.x
is of type: bit-field of typesigned int
.This is different than
signed int
because the two types don't share the same constraints and requirements.For example:
The C11 specification certainly does not make this clear, and is perhaps deficient.
I believe that
foo.x
is an lvalue with type other thanint
, but my justification is pretty weak:6.2.7 paragraph 1 says:
6.3 paragraph 2 says:
If
foo.x
is an lvalue of typeint
, then it would be compatible with otherint
s sofoo.x = 5
should result infoo.x
having value5
(per 6.3p2). That obviously can't happen, suggesting thatfoo.x
is not compatible withint
, suggesting thatfoo.x
is not an lvalue of typeint
.It doesn't really make sense that
foo.x
isn't compatible withint
. Maybe no conversion (in the 6.3.1 sense) occurs, and thatfoo.x
obtains its value via some mechanism not discussed in the standard. Or maybe I'm misunderstanding what "arithmetic operands" means, and that 6.3.1 doesn't apply to lvalues.There's also 6.3.1.1 paragraph 1 bullet 2, which says:
foo.x
has less precision than an ordinaryint
(when used as an lvalue, not when it "is converted to the value stored in the designated object" as described in 6.3.2.1p2), so it must have a different integer conversion rank. This also suggests that it is not anint
.But I'm not sure that my interpretation is valid or matches the intention of the committee.
I would recommend submitting a defect report about this.
Given that you included the
signed
qualifier, then the only values that can be stored in the 1-bit bit field are indeed -1 and 0. If you'd omitted the qualifier, it would be implementation defined whether the 'plain'int
bit field was signed or unsigned. If you'd specifiedunsigned int
, of course, the values would be 0 and +1.The relevant sections of the standard are:
The footnote 125 points to:
The C11 Standard states in 6.7.2.1p5:
This is a constraint, meaning, if a program declares a bit field with a type that does not fall into one of the categories above, a diagnostic must be printed.
However it then goes on to say in 6.7.2.1p10:
I believe what they mean is that, while you must declare the bit field with something like
signed int x:n
, the type of the lvalue expressionfoo.x
is some other signed integer type, call it T. T is a signed integer type consisting of n bits and must comply with the constraints on all signed integer types given in Sec. 6.2.6. But T is not necessarily compatible with the standard signed integer type namedsigned int
. (In fact, the only situation in which it is possible for T to be compatible with that standard type is if n happens to equal the number of bits in a signed int.)Unfortunately, the Standard does not provide any means to name the type T, so I can't see how it can be used in a
_Generic
, at least, not in a portable way. Specific implementations of the C language may provide a mechanism to name this type, but the Standard does not force them to.As Jonathan already cited, p5 clearly states what the type a bit-field has.
What you should have also in mind is that there is a special rule for bit-field arithmetic conversions in 6.3.1.1, basically stating that if an
int
can represent all values such a bit-field converts to anint
in most expressions.What the type would be in a
_Generic
should be the declared type (modulo the sign glitch), since it seems to be consensus that arithmetic conversions don't apply, there. Socould give you different results if
X
is an unsigned bit-field with a width that has all values fit into anint
.The results of how 1 compiler treats the bit field types is shown below.
The 8-bit and 32-bit fields match the usual suspects.
What is the type of a 1-bit bitfield? As others have cited, its "name" is not clearly specified, but it is not any of the expected standard types.
This does not cite a specification, but does demonstrate how a respected compiler interpreted the C spec.
GNU C11 (GCC) version 5.3.0 (i686-pc-cygwin)
compiled by GNU C version 5.3.0, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3
Output
Note with
-Wconversion
and the below code, I get this warning. So that is at least what one compiler calls its small bit field type:unsigned char:3
.