Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.std.c Subject: Re: bit-fields of type unsigned long and unsigned long long Date: Thu, 24 Jun 2021 11:06:37 -0700 Organization: None to speak of Lines: 115 Message-ID: <878s2zw30y.fsf@nosuchdomain.example.com> References: <86fsx8bh88.fsf@linuxsc.com> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: reader02.eternal-september.org; posting-host="70e67a5c90413ba34e7665d352b91ebe"; logging-data="15350"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18wC1KmaJ1XdOnQV4JJcQox" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) Cancel-Lock: sha1:pla7SQ2iSaAtpsfWXGZaPNbzJHg= sha1:iHQHicV/o3pMUgdn47oDPmGBqsI= Xref: csiph.com comp.std.c:6242 David Brown writes: > On 23/06/2021 19:53, Tim Rentsch wrote: >> Philipp Klaus Krause writes: >>> Since bit-fields of type unsigned long and unsigned long long are >>> useful, commonly suppoted by implementations, and commonly used, I'd >>> like to see the standard support them. >>> >>> Here's a draft of a proposal for that: >>> >>> http://www.colecovision.eu/stuff/proposal-unsigned-long-bit-field.html >> >> Here is a possible (and simpler) alternative. >> >> Type specifier for bit-fields is _Bool, int, signed, or unsigned >> (with signed int and unsigned int being synonymous with signed >> and unsigned, respectively). >> >> Bit-fields of type _Bool act just like they do now. >> >> Bit-fields of type int are either the same as an unsigned >> bit-field or the same as a signed bit-field, with the choice >> being implementation-defined, just like they are now. >> >> Bit-fields of types signed and unsigned may use widths up to the >> widths of intmax_t and uintmax_t, respectively. >> >> The type of a signed bit-field is the first of signed, long, >> long long, and intmax_t, that is wide enough to hold all the >> possible values of the bit-field. >> >> The type of an unsigned bit-field is the first of unsigned, >> unsigned long, unsigned long long, and uintmax_t, that is wide >> enough to hold all the possible values of the bit-field. >> >> For compatibility with current integer promotion rules, an access >> for an unsigned bit-field whose range of possible values are all >> representable within the range of signed int yields a value that >> has been promoted to type signed int, just like such things are >> done now. In all other cases the type of a bit-field access >> is the type of the bit-field, as stated above. >> >> (Personally I like this approach better than allowing different >> integer types as bit-field specifiers.) > > This would give a very different result from the way compilers implement > bitfields today. In particular, consider : > > sizeof(struct { int8_t a : 1; }); > > today, that is 1 on compilers that accept any integer type in bit > fields. With your proposal, it would be sizeof(int). How does that follow? The bit field occupies only 1 bit. Why should its underlying type affect the size of the structure? I know that with gcc and clang, these structures have different sizes: struct { _Bool bitfield:1; } struct { unsigned bitfield:1; } but I don't see anything in the standard that suggests they should. (I vaguely recall that it's an ABI requirement.) > sizeof(struct { int64_t a : 1; }); > > today, that is 8 (assuming 8-bit char), while with your proposal it > would be sizeof(int). > > It would be conceivable that an implementation could make the types of > the bitfields act the way you describe, while keeping the sizes (and > alignments, padding, splitting, etc.) of the bitfields the same as > today. But it would be needlessly confusing, and lead to other > differences (such as when the bitfields are used in other expressions). > The only sane approach to bitfield types is that the type of the > bitfield is the type given by the programmer when they declared the > bitfield. (And here I agree with Keith that it is unfortunate that a > bitfield declared as type "int" might be signed or unsigned.) The "type of a bit-field" seems like a tricky concept. Consider: struct { unsigned int bf: 1; }; N1570 6.7.2.1p5 says: 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. which implies that bf is of type unsigned int. But p10 says: A bit-field is interpreted as having a signed or unsigned integer type consisting of the specified number of bits. So the type of bf is an unsigned type consisting of 1 bit, and clearly that's not unsigned int. I think p5 is referring to the type used to define the bit-field, and p10 is referring to the (anonymous) type that the bit-field actually ends up having. IMHO it could be worded more clearly. > I also note that your "simpler" alternative is significantly longer than > Philipp's original proposal or the even simpler, obvious, and currently > implemented change: > > "A bit-field shall have a type that is a qualified or unqualified > version of an integer type". > > That's what compilers do today, that's what programmers use today, and > it is shorter, simpler and clearer than any other version. And it is > consistent with C++ (which also allows enumeration types - which would > be another nice addition to the C standard). Any proposal should take C++ into account, both to steal ideas and to avoid inconsistencies (like C++'s statement that if the specified width is more than the width of the specified type, the extra bits are padding bits). -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */