Authors: Jay Ghiron
Date: 2026-06-10
Submitted against: C23
Status: Open
Cross-references: 0120, 1076
There have been previous issues raised regarding expressions which use the values of bit-fields outside of contexts which they occur in promotions, but those do not seem to be resolved. See also N2958.
typeof(0,(struct{unsigned y:1;}){}.y)x;
Is this declaration valid? That is, if the right operand of a comma operator is a bit-field should the resulting expression be a bit-field too? This also applies to assignment operators where the left operand is a bit-field.
struct{unsigned z:1;}s;
int main(){
auto a=s.z;
}
Is this declaration in main valid? That is, should auto type
deduction be valid for bit-fields?
struct{unsigned w:1;}r;
int main(){
return _Generic(r.w,int:1,unsigned:2,default:3);
}
What value should be returned from this program? _Generic is the
only context currently which can inspect the types of bit-field
expressions regardless of the answers to the previous questions. GCC
returns three, Clang and MSVC return two.
#include<stdbit.h>
#include<stdckdint.h>
struct{unsigned b:1;}a;
int c;
int main(){
stdc_leading_zeros(a.b);
ckd_add(&c,a.b,a.b);
}
Is this program valid? That is, should generic functions be expected
to handle bit-fields? I assume that the <tgmath.h> functions should
be able to handle bit-fields, since there are no issues with
implementing that. GCC has stdc_leading_zeros here return one,
while Clang has it return UINT_WIDTH.
A bit-field is interpreted as having a signed or unsigned integer type consisting of the specified number of bits.
(C23 6.7.3.2 "Structure and union specifiers" paragraph 12.)
Must this signed or unsigned integer type have the same signedness as the type specified in the bit-field declaration? There does not appear to be anything requiring it, but it would result in a large change to the range of representable values.
If the type specified in the bit-field declaration is not bool and
the width is one, can this signed or unsigned integer type be bool?
This difference is observable in whether or not conversion to the
bit-field type in assignment will convert using the semantics of
bool. In C2Y this possibility is removed, but it also disallows a
bool bit-field from using the type bool which seems unintended.
Note that GCC still uses the type bool when attempting to observe
the type of a bool bit-field using _Generic, even in C2Y.
Though this does not cause any issues, it may be useful to add "nonzero-width" to this text like in the next sentence to avoid implying that an unnamed zero width bit-field has an integer type with a width of zero.
If the answers to question one and question two are that those declarations are valid, then what category of integer type do the types of bit-fields belong to (standard, extended, or bit-precise)? For example, would the following be valid?
typedef typeof(0,(struct{unsigned d:1;}){}.d)T;
enum E:T{e};
Additionally, should <stdbit.h> and <stdckdint.h> be expected to
work with T?
If the answers to question one and question two are that those declarations are valid, then does the bit-field propagate when using the type of a bit-field? For example
struct S{unsigned _BitInt(3)f:2;};
typedef typeof(0,(struct S){}.f)U;
struct R{U u;};
int main(){
struct S v={};
U g={};
typedef typeof(+v.f)V;
typedef typeof(+g)V;
}
Is the member u of R considered a bit-field? Is typeof(+g)
equivalent to unsigned _BitInt(3) because it gets promoted like a
bit-field? GCC does not seem to do it but, but it is unclear how
typeof(+v.f) should at the same time result in unsigned _BitInt(3)
since it undergoes lvalue conversions which results in the type U
being promoted just like typeof(+g).
If the answers to question one and question two are that those declarations are valid, then is the following valid?
typedef typeof(0,(struct{unsigned q:1;}){}.q)W;
typedef typeof(0,(struct{unsigned p:1;}){}.p)W;
That is, must the same type be generated for these two different bit-fields? If not, would there be any common initial sequence between these two structure types?
If the answers to question one and question two are that those
declarations are valid, then do bit-fields whose type is the type of a
bool bit-field have the same semantics as bool?
struct{typeof(0,(struct{bool m:1;}){}.m)l:1;}k;
/* assume this bit-field is supported */
int main(){
k.l=2;
return k.l;
/* is zero or one returned? */
}
See also issue 1076, which discusses this but for
enumerated types compatible with bool.
I think it is also worth mentioning that C and C++ diverge on a few
aspects of bit-fields other than just the bit-field type. The program
in DR 120 in C++ may print "0 0", "0 1", "1 0", or "1
1". C++ clearly makes initializations and assignments with values
that are not representable by the bit-field after conversion result in
unspecified values. Note that a bool bit-field in C++ never has
this condition apply, since the conversion happens first before
initialization or assignment so the value will always be
representable. Additionally, C++ makes the following undefined:
struct{bool h:1,i:1;}j;
int main(){
(j.h=1)+(j.i=1);
}
Since it defines unsequenced accesses in terms of memory locations, and these two bit-fields are part of the same memory location.