Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

"A mind is a terrible thing to have leaking out your ears." -- The League of Sadistic Telepaths


devel / comp.std.c / Re: bit-fields of type unsigned long and unsigned long long

SubjectAuthor
* bit-fields of type unsigned long and unsigned long longPhilipp Klaus Krause
+* Re: bit-fields of type unsigned long and unsigned long longDavid Brown
|`* Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
| `* Re: bit-fields of type unsigned long and unsigned long longPhilipp Klaus Krause
|  +* Re: bit-fields of type unsigned long and unsigned long longDavid Brown
|  |`* Re: bit-fields of type unsigned long and unsigned long longPhilipp Klaus Krause
|  | `* Re: bit-fields of type unsigned long and unsigned long longDavid Brown
|  |  `* Re: bit-fields of type unsigned long and unsigned long longPhilipp Klaus Krause
|  |   +* Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
|  |   |`* Re: bit-fields of type unsigned long and unsigned long longPhilipp Klaus Krause
|  |   | `* Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
|  |   |  `- Re: bit-fields of type unsigned long and unsigned long longDavid Brown
|  |   `- Re: bit-fields of type unsigned long and unsigned long longDavid Brown
|  `- Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
+* Re: bit-fields of type unsigned long and unsigned long longPhilipp Klaus Krause
|`- Re: bit-fields of type unsigned long and unsigned long longPhilipp Klaus Krause
`* Re: bit-fields of type unsigned long and unsigned long longTim Rentsch
 +* Re: bit-fields of type unsigned long and unsigned long longPhilipp Klaus Krause
 |`* Re: bit-fields of type unsigned long and unsigned long longTim Rentsch
 | +* Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
 | |+- Re: bit-fields of type unsigned long and unsigned long longDavid Brown
 | |`- Re: bit-fields of type unsigned long and unsigned long longTim Rentsch
 | `* Re: bit-fields of type unsigned long and unsigned long longPhilipp Klaus Krause
 |  `- Re: bit-fields of type unsigned long and unsigned long longTim Rentsch
 `* Re: bit-fields of type unsigned long and unsigned long longDavid Brown
  `* Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
   `* Re: bit-fields of type unsigned long and unsigned long longDavid Brown
    `* Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
     `* Re: bit-fields of type unsigned long and unsigned long longDavid Brown
      +* Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
      |`* Re: bit-fields of type unsigned long and unsigned long longDavid Brown
      | +* Re: bit-fields of type unsigned long and unsigned long longBen Bacarisse
      | |+* Re: bit-fields of type unsigned long and unsigned long longDavid Brown
      | ||+* Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
      | |||`* Re: bit-fields of type unsigned long and unsigned long longDavid Brown
      | ||| `- Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
      | ||`- Re: bit-fields of type unsigned long and unsigned long longBen Bacarisse
      | |`- Re: bit-fields of type unsigned long and unsigned long longTim Rentsch
      | `- Re: bit-fields of type unsigned long and unsigned long longKeith Thompson
      `* Re: bit-fields of type unsigned long and unsigned long longPhilipp Klaus Krause
       +- Re: bit-fields of type unsigned long and unsigned long longDavid Brown
       `- Re: bit-fields of type unsigned long and unsigned long longJakob Bohm

Pages:12
Re: bit-fields of type unsigned long and unsigned long long

<87v962vrh3.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=270&group=comp.std.c#270

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Thu, 24 Jun 2021 15:16:08 -0700
Organization: None to speak of
Lines: 55
Message-ID: <87v962vrh3.fsf@nosuchdomain.example.com>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="e76a60976a03f7b22ccc859f0f74fb19";
logging-data="4370"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1832IxFKjvbQdVhs8one5z6"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:jcseywVi4zFvne2jiLox3XIfCyw=
sha1:4iszxqjfln8IZLbURXeoD3PVSCE=
 by: Keith Thompson - Thu, 24 Jun 2021 22:16 UTC

David Brown <david.brown@hesbynett.no> writes:
> On 24/06/2021 20:06, Keith Thompson wrote:
>> David Brown <david.brown@hesbynett.no> writes:
[...]
>>> 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?
>
> The current practice is that the size (and alignment) of the struct or
> its parts comes from the type used to declare the bit-field - just as
> for any other field. As I said below, it would be conceivable for a
> compiler to use the programmer's specified type to set the size of the
> containing struct or addressable storage unit, while ignoring it for the
> type of the field and how it is interpreted when used in an expression.
> That would, however, seem arbitrary and counter-intuitive, as well as
> being contrary to current practice and (if my interpretation is correct
> - but I might be wrong here) to C++ standards.

(For simplicity, assume CHAR_BIT==8 and sizeof(int)==4.)

I understand that it's existing practice, but it just doesn't make any
sense to me. If I define a struct with a bit-field defined as "unsigned
int:1", it's a single bit, not a 32-bit unsigned int object. I can pack
8 of them into a single byte. I just don't see why the declared type
of a bit field should affect the size of the containing structure when
it has no effect on the size of the bit field itself. The structure
doesn't *need* those 32 bits of storage. If I add a second unsigned:1
bit-field, the structure doesn't grow by another 32 bits.

As N1570 6.7.2.1p10 says, "A bit-field is interpreted as having a signed
or unsigned integer type consisting of the specified number of bits.",
so the bit-field object isn't really of type unsigned int.

For an implementation that doesn't support types other than the
required ones, any struct with a 2-bit bit-field would have to be
at least 32 bits, while a struct with an unsigned char member could
be as small as 8 bits. (Same for a 1-bit bit-field pre-C99.) That
seems to me like an arbitrary restriction.

I don't use bit-fields much, so maybe I'm missing some reason why this
behavior is reasonable and/or useful.

[...]

--
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 */

Re: bit-fields of type unsigned long and unsigned long long

<sb44vv$frb$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=271&group=comp.std.c#271

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 10:43:42 +0200
Organization: A noiseless patient Spider
Lines: 114
Message-ID: <sb44vv$frb$1@dont-email.me>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 25 Jun 2021 08:43:43 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="e2dcdf334c1a7b567a02d744e0595df8";
logging-data="16235"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/BtoHpo4KVXiGKj8NWdqKYnBOZj4A/1bo="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.10.0
Cancel-Lock: sha1:ftP6mynOkqJIp69V98Y5r0HPtRI=
In-Reply-To: <87v962vrh3.fsf@nosuchdomain.example.com>
Content-Language: en-GB
 by: David Brown - Fri, 25 Jun 2021 08:43 UTC

On 25/06/2021 00:16, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
>> On 24/06/2021 20:06, Keith Thompson wrote:
>>> David Brown <david.brown@hesbynett.no> writes:
> [...]
>>>> 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?
>>
>> The current practice is that the size (and alignment) of the struct or
>> its parts comes from the type used to declare the bit-field - just as
>> for any other field. As I said below, it would be conceivable for a
>> compiler to use the programmer's specified type to set the size of the
>> containing struct or addressable storage unit, while ignoring it for the
>> type of the field and how it is interpreted when used in an expression.
>> That would, however, seem arbitrary and counter-intuitive, as well as
>> being contrary to current practice and (if my interpretation is correct
>> - but I might be wrong here) to C++ standards.
>
> (For simplicity, assume CHAR_BIT==8 and sizeof(int)==4.)
>
> I understand that it's existing practice, but it just doesn't make any
> sense to me. If I define a struct with a bit-field defined as "unsigned
> int:1", it's a single bit, not a 32-bit unsigned int object. I can pack
> 8 of them into a single byte. I just don't see why the declared type
> of a bit field should affect the size of the containing structure when
> it has no effect on the size of the bit field itself. The structure
> doesn't *need* those 32 bits of storage. If I add a second unsigned:1
> bit-field, the structure doesn't grow by another 32 bits.
>
> As N1570 6.7.2.1p10 says, "A bit-field is interpreted as having a signed
> or unsigned integer type consisting of the specified number of bits.",
> so the bit-field object isn't really of type unsigned int.
>
> For an implementation that doesn't support types other than the
> required ones, any struct with a 2-bit bit-field would have to be
> at least 32 bits, while a struct with an unsigned char member could
> be as small as 8 bits. (Same for a 1-bit bit-field pre-C99.) That
> seems to me like an arbitrary restriction.
>
> I don't use bit-fields much, so maybe I'm missing some reason why this
> behavior is reasonable and/or useful.
>
> [...]
>

As I see it, bit-fields are used for two main purposes.

One is for structures internal to a program, in order to reduce space.
There are two typical reasons for that. You might have a small embedded
system with extremely small ram size (though these are getting less
common, and since they are very rarely used with anything newer than
C99, changes to the standard matter little there). Or you might have a
bigger system with very large quantities of data, so that packing the
data is important for efficiency. Common for these is that you don't
really care about things like ordering, but you /do/ care that the sizes
are what you expect. In particular, for efficiency on big systems too
small is not better than too big - an array of 60 byte structs (with 4
byte alignment) is going to be a lot slower than an array of 64 byte
structs for many purposes.

The other main use for bitfields is for matching external structures.
These can be part of file formats, network packet formats, calls to
functions from other languages, or hardware and peripherals. For this
kind of use, precise specifications of all sizes, alignments, bit
ordering, etc., is essential. The alternative is to use masks and
shifting which is ugly and error-prone, but more portable.

The bit-field requirements in the C specifications today are too limited
and under-specified to be of much use for anything - they are not enough
to do a good job of any common use-cases. (They could be useful for
making compact structures for large arrays in the days before caches,
when precise sizes mattered less.)

The practical reality of bit-fields is that people use them based on the
specifications given by their compiler and/or target ABI, using
extensions provided by almost all good compilers (allowing any integer
type or enumeration type), or using undocumented assumptions about
sizes, alignments, ordering, etc., for their compiler and target.

A change to the C standards which does not take them nearer to
guaranteeing the practical use of today's tools and needs of today's
programmers, is useless.

A change to the C standards that goes against today's practice is worse
than useless.

A change that differs from the C++ standards (except in regarding the
silly support for over-sized bit-fields) is worse than useless.

A change that involves long, complicated reasoning about sizes and types
but provides enough implementation-defined wiggle room to fit with
today's implementations, is useless. The last thing the C standards
need is more language that is confusing, open to interpretation, vague,
and unhelpful to either compiler implementers or C programmers.

If the C standard can't be changed to explicitly allow /all/ integer
types in bit-fields, then making any change at all here is a waste of
time and effort.

If it can't be changed to mandate that the size of the allocation units
matches the size of the type specified by the programmer as the
bit-field type, then it must be left as it is (implementation-defined).

If it can't be changed to mandate that the type of the bit-field matches
the type specified by the programmer, then it must be left as it is.

Re: bit-fields of type unsigned long and unsigned long long

<87a6neuxjo.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=272&group=comp.std.c#272

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 02:02:35 -0700
Organization: None to speak of
Lines: 160
Message-ID: <87a6neuxjo.fsf@nosuchdomain.example.com>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="e76a60976a03f7b22ccc859f0f74fb19";
logging-data="6434"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18acQOCLi9orzTkomIvmzgk"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:aKomjdb4JMP5WDNt+WJybzTwWtM=
sha1:r/1SbSXSqYJXvTVyFc+ZNa0GeXU=
 by: Keith Thompson - Fri, 25 Jun 2021 09:02 UTC

David Brown <david.brown@hesbynett.no> writes:
> On 25/06/2021 00:16, Keith Thompson wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>> On 24/06/2021 20:06, Keith Thompson wrote:
>>>> David Brown <david.brown@hesbynett.no> writes:
>> [...]
>>>>> 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?
>>>
>>> The current practice is that the size (and alignment) of the struct or
>>> its parts comes from the type used to declare the bit-field - just as
>>> for any other field. As I said below, it would be conceivable for a
>>> compiler to use the programmer's specified type to set the size of the
>>> containing struct or addressable storage unit, while ignoring it for the
>>> type of the field and how it is interpreted when used in an expression.
>>> That would, however, seem arbitrary and counter-intuitive, as well as
>>> being contrary to current practice and (if my interpretation is correct
>>> - but I might be wrong here) to C++ standards.
>>
>> (For simplicity, assume CHAR_BIT==8 and sizeof(int)==4.)
>>
>> I understand that it's existing practice, but it just doesn't make any
>> sense to me. If I define a struct with a bit-field defined as "unsigned
>> int:1", it's a single bit, not a 32-bit unsigned int object. I can pack
>> 8 of them into a single byte. I just don't see why the declared type
>> of a bit field should affect the size of the containing structure when
>> it has no effect on the size of the bit field itself. The structure
>> doesn't *need* those 32 bits of storage. If I add a second unsigned:1
>> bit-field, the structure doesn't grow by another 32 bits.
>>
>> As N1570 6.7.2.1p10 says, "A bit-field is interpreted as having a signed
>> or unsigned integer type consisting of the specified number of bits.",
>> so the bit-field object isn't really of type unsigned int.
>>
>> For an implementation that doesn't support types other than the
>> required ones, any struct with a 2-bit bit-field would have to be
>> at least 32 bits, while a struct with an unsigned char member could
>> be as small as 8 bits. (Same for a 1-bit bit-field pre-C99.) That
>> seems to me like an arbitrary restriction.
>>
>> I don't use bit-fields much, so maybe I'm missing some reason why this
>> behavior is reasonable and/or useful.
>>
>> [...]
>>
>
> As I see it, bit-fields are used for two main purposes.
>
> One is for structures internal to a program, in order to reduce space.
> There are two typical reasons for that. You might have a small embedded
> system with extremely small ram size (though these are getting less
> common, and since they are very rarely used with anything newer than
> C99, changes to the standard matter little there). Or you might have a
> bigger system with very large quantities of data, so that packing the
> data is important for efficiency. Common for these is that you don't
> really care about things like ordering, but you /do/ care that the sizes
> are what you expect. In particular, for efficiency on big systems too
> small is not better than too big - an array of 60 byte structs (with 4
> byte alignment) is going to be a lot slower than an array of 64 byte
> structs for many purposes.
>
> The other main use for bitfields is for matching external structures.
> These can be part of file formats, network packet formats, calls to
> functions from other languages, or hardware and peripherals. For this
> kind of use, precise specifications of all sizes, alignments, bit
> ordering, etc., is essential. The alternative is to use masks and
> shifting which is ugly and error-prone, but more portable.
>
> The bit-field requirements in the C specifications today are too limited
> and under-specified to be of much use for anything - they are not enough
> to do a good job of any common use-cases. (They could be useful for
> making compact structures for large arrays in the days before caches,
> when precise sizes mattered less.)
>
> The practical reality of bit-fields is that people use them based on the
> specifications given by their compiler and/or target ABI, using
> extensions provided by almost all good compilers (allowing any integer
> type or enumeration type), or using undocumented assumptions about
> sizes, alignments, ordering, etc., for their compiler and target.
>
> A change to the C standards which does not take them nearer to
> guaranteeing the practical use of today's tools and needs of today's
> programmers, is useless.
>
> A change to the C standards that goes against today's practice is worse
> than useless.
>
> A change that differs from the C++ standards (except in regarding the
> silly support for over-sized bit-fields) is worse than useless.
>
> A change that involves long, complicated reasoning about sizes and types
> but provides enough implementation-defined wiggle room to fit with
> today's implementations, is useless. The last thing the C standards
> need is more language that is confusing, open to interpretation, vague,
> and unhelpful to either compiler implementers or C programmers.
>
> If the C standard can't be changed to explicitly allow /all/ integer
> types in bit-fields, then making any change at all here is a waste of
> time and effort.
>
> If it can't be changed to mandate that the size of the allocation units
> matches the size of the type specified by the programmer as the
> bit-field type, then it must be left as it is (implementation-defined).
>
> If it can't be changed to mandate that the type of the bit-field matches
> the type specified by the programmer, then it must be left as it is.

I don't see an answer to my question anywhere in there.

To be perhaps a bit clearer, when I compile this program with gcc or
clang:

#include <stdio.h>
#include <limits.h>
int main(void) {
struct has_bit_field {
unsigned bit_field : 1;
};
struct has_unsigned_char {
unsigned char uc;
};
printf("CHAR_BIT = %d\n", CHAR_BIT);
printf("sizeof (unsigned) = %zu\n", sizeof (unsigned));
printf("sizeof (struct has_bit_field) = %zu\n", sizeof (struct has_bit_field));
printf("sizeof (struct has_unsigned_char) = %zu\n", sizeof (struct has_unsigned_char));
}

the output on my system is:

CHAR_BIT = 8
sizeof (unsigned) = 4
sizeof (struct has_bit_field) = 4
sizeof (struct has_unsigned_char) = 1

What is the rationale for a bit-field forcing the structure to be
expanded to 4 bytes, when the bit-field itself is only 1 bit?
Why does a 1-bit bit-field for a bigger structure size than an 8-bit
unsigned char member?

I understand that it's implementation-defined, probably ABI-defined, and
that changing it would break existing code that depends on this
behavior. I'm trying to understand why it was defined this way in the
first place. I see nothing in the C standard that suggests this (though
of course it does allow it).

I would have assumed that both struct has_bit_field and struct
has_unsigned_char could sensibly have a size of 1 byte.

--
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 */

Re: bit-fields of type unsigned long and unsigned long long

<sb4g65$4m4$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=273&group=comp.std.c#273

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 13:54:44 +0200
Organization: A noiseless patient Spider
Lines: 88
Message-ID: <sb4g65$4m4$1@dont-email.me>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me> <87a6neuxjo.fsf@nosuchdomain.example.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 25 Jun 2021 11:54:45 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="e2dcdf334c1a7b567a02d744e0595df8";
logging-data="4804"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18hh22/agbc224KgVLr9q84e+UWIj/q3Po="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.10.0
Cancel-Lock: sha1:iAnKJfx/Q38Tw1r3kLm9jEB3S24=
In-Reply-To: <87a6neuxjo.fsf@nosuchdomain.example.com>
Content-Language: en-GB
 by: David Brown - Fri, 25 Jun 2021 11:54 UTC

On 25/06/2021 11:02, Keith Thompson wrote:

>
> I don't see an answer to my question anywhere in there.
>
> To be perhaps a bit clearer, when I compile this program with gcc or
> clang:
>
> #include <stdio.h>
> #include <limits.h>
> int main(void) {
> struct has_bit_field {
> unsigned bit_field : 1;
> };
> struct has_unsigned_char {
> unsigned char uc;
> };
> printf("CHAR_BIT = %d\n", CHAR_BIT);
> printf("sizeof (unsigned) = %zu\n", sizeof (unsigned));
> printf("sizeof (struct has_bit_field) = %zu\n", sizeof (struct has_bit_field));
> printf("sizeof (struct has_unsigned_char) = %zu\n", sizeof (struct has_unsigned_char));
> }
>
> the output on my system is:
>
> CHAR_BIT = 8
> sizeof (unsigned) = 4
> sizeof (struct has_bit_field) = 4
> sizeof (struct has_unsigned_char) = 1
>
> What is the rationale for a bit-field forcing the structure to be
> expanded to 4 bytes, when the bit-field itself is only 1 bit?
> Why does a 1-bit bit-field for a bigger structure size than an 8-bit
> unsigned char member?

It lets the /programmer/ make the choice.

When I write "uint16_t x : 3;", I mean "Make a container field of size
and type uint16_t, and allocate 3 bits of it to x. If there is already
a container field of this type and size with enough free space just
before x, add it to the same container".

That is the function I want bit-fields to have. That is what makes them
useful in a wide range of use-cases. There are some situations where
all you need is to say "x doesn't have to hold more than 3 bits of
information, and I'd like the surrounding structure to be reasonably
small". But often you want to have the control.

Another situation where you need precise control for hardware registers
is in the access sizes for volatile data (and hardware registers are
usually accessed as volatile). Access size typically makes a /huge/
difference in the hardware. If the bit-field "x" above is part of a
volatile structure, then all reads and writes to it must be done using
16-bit accesses. (gcc had a bug for a while in their ARM port that
meant a smaller access size would be used for smaller bit size of
fields, giving 8-bit accesses for a 3 bit bit-field regardless of the
declared type. This caused a lot of problems.)

All in all, I want the type I give in the bit-field declaration to be
used by the compiler. Otherwise, what's the point of having it at all?

>
> I understand that it's implementation-defined, probably ABI-defined, and
> that changing it would break existing code that depends on this
> behavior. I'm trying to understand why it was defined this way in the
> first place. I see nothing in the C standard that suggests this (though
> of course it does allow it).
>

The C standard doesn't say anything about such sizes - it wouldn't make
much sense to do so when there are so limited options mandated for
bit-field types in the standard at the moment. The standard basically
abdicates many of the important aspects of bit-fields to the
implementation - it gives the syntax but not the details.

> I would have assumed that both struct has_bit_field and struct
> has_unsigned_char could sensibly have a size of 1 byte.
>

I would not.

And therein, perhaps, is the biggest problem with bit-fields in C.
Because there is virtually no guidance in the standards in this respect,
people with different experiences, practices and needs for the language
can have widely different expectations or assumptions about them. (I
expect that in actual code you would not make such assumptions, since I
believe you often have to write more portable code that avoids relying
on implementation-defined behaviour.)

Re: bit-fields of type unsigned long and unsigned long long

<8735t6no5f.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=274&group=comp.std.c#274

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 13:07:24 +0100
Organization: A noiseless patient Spider
Lines: 59
Message-ID: <8735t6no5f.fsf@bsb.me.uk>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me> <87a6neuxjo.fsf@nosuchdomain.example.com>
<sb4g65$4m4$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="c9051376ae85fc2e6ee14100b71f4598";
logging-data="6441"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+u8GPPkqebSuMpvo7rimXlISF584oeMtI="
Cancel-Lock: sha1:b+q7PJf73Isld8htBUaVACF4/+I=
sha1:nMaoM91iUeDC4x9Ul3OFgbziOVM=
X-BSB-Auth: 1.3ed954c00e97115c8778.20210625130724BST.8735t6no5f.fsf@bsb.me.uk
 by: Ben Bacarisse - Fri, 25 Jun 2021 12:07 UTC

David Brown <david.brown@hesbynett.no> writes:

> On 25/06/2021 11:02, Keith Thompson wrote:
>
>>
>> I don't see an answer to my question anywhere in there.
>>
>> To be perhaps a bit clearer, when I compile this program with gcc or
>> clang:
>>
>> #include <stdio.h>
>> #include <limits.h>
>> int main(void) {
>> struct has_bit_field {
>> unsigned bit_field : 1;
>> };
>> struct has_unsigned_char {
>> unsigned char uc;
>> };
>> printf("CHAR_BIT = %d\n", CHAR_BIT);
>> printf("sizeof (unsigned) = %zu\n", sizeof (unsigned));
>> printf("sizeof (struct has_bit_field) = %zu\n", sizeof (struct has_bit_field));
>> printf("sizeof (struct has_unsigned_char) = %zu\n", sizeof (struct has_unsigned_char));
>> }
>>
>> the output on my system is:
>>
>> CHAR_BIT = 8
>> sizeof (unsigned) = 4
>> sizeof (struct has_bit_field) = 4
>> sizeof (struct has_unsigned_char) = 1
>>
>> What is the rationale for a bit-field forcing the structure to be
>> expanded to 4 bytes, when the bit-field itself is only 1 bit?
>> Why does a 1-bit bit-field for a bigger structure size than an 8-bit
>> unsigned char member?
>
> It lets the /programmer/ make the choice.
>
> When I write "uint16_t x : 3;", I mean "Make a container field of size
> and type uint16_t, and allocate 3 bits of it to x. If there is already
> a container field of this type and size with enough free space just
> before x, add it to the same container".

struct eg {
unsigned x : 3;
unsigned : 16-3;
};

seems just as clear to me. Both rely on implementation-defined
behaviour, but had gcc taken the other route, the programmer would still
have the choice.

It seems wrong for bit fields have an explicit type at all. What they
need is only the signed/unsigned distinction for which there are already
keywords.

--
Ben.

Re: bit-fields of type unsigned long and unsigned long long

<sb4j1a$dmn$1@solani.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=275&group=comp.std.c#275

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!feeder5.news.weretis.net!news.solani.org!.POSTED!not-for-mail
From: pkk...@spth.de (Philipp Klaus Krause)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 14:43:22 +0200
Message-ID: <sb4j1a$dmn$1@solani.org>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 25 Jun 2021 12:43:22 -0000 (UTC)
Injection-Info: solani.org;
logging-data="14039"; mail-complaints-to="abuse@news.solani.org"
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
Thunderbird/78.11.0
Content-Language: en-US
Cancel-Lock: sha1:WVa7kzBAaPm6Cwhy/g5WgfZyfT0=
In-Reply-To: <sb44vv$frb$1@dont-email.me>
X-User-ID: eJwNyMkBwDAIA7CVwByh4xSK9x8h1VNhqTnHM9KDQSAK63DSxF5XmnZSRv+lJvbBGVh91dI7Fwa2EL4=
 by: Philipp Klaus Krause - Fri, 25 Jun 2021 12:43 UTC

Am 25.06.21 um 10:43 schrieb David Brown:

>
> As I see it, bit-fields are used for two main purposes.
>
> One is for structures internal to a program, in order to reduce space.
> There are two typical reasons for that. You might have a small embedded
> system with extremely small ram size (though these are getting less
> common, and since they are very rarely used with anything newer than
> C99, changes to the standard matter little there).
If newer standards are rarely used for programming small embedded
systems, is it because the standard might have been diverging from their
requirements?
Is it because newer standards take so much effort to implement that
compilers other than GCC and clang lack the manpower to implement them
timely?
Is it because users follow a coding standard, such as MISRA, that takes
a while to update for new C standards?

Re: bit-fields of type unsigned long and unsigned long long

<sb4l0o$v7u$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=276&group=comp.std.c#276

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 15:17:11 +0200
Organization: A noiseless patient Spider
Lines: 120
Message-ID: <sb4l0o$v7u$1@dont-email.me>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me> <87a6neuxjo.fsf@nosuchdomain.example.com>
<sb4g65$4m4$1@dont-email.me> <8735t6no5f.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 25 Jun 2021 13:17:12 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="e2dcdf334c1a7b567a02d744e0595df8";
logging-data="31998"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/FTEFWuXNijbpZwA9wwW6JtdwpkvngocY="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.10.0
Cancel-Lock: sha1:BqcH1UDiCmnzz4M6IMe49LUsBsk=
In-Reply-To: <8735t6no5f.fsf@bsb.me.uk>
Content-Language: en-GB
 by: David Brown - Fri, 25 Jun 2021 13:17 UTC

On 25/06/2021 14:07, Ben Bacarisse wrote:
> David Brown <david.brown@hesbynett.no> writes:
>
>> On 25/06/2021 11:02, Keith Thompson wrote:
>>
>>>
>>> I don't see an answer to my question anywhere in there.
>>>
>>> To be perhaps a bit clearer, when I compile this program with gcc or
>>> clang:
>>>
>>> #include <stdio.h>
>>> #include <limits.h>
>>> int main(void) {
>>> struct has_bit_field {
>>> unsigned bit_field : 1;
>>> };
>>> struct has_unsigned_char {
>>> unsigned char uc;
>>> };
>>> printf("CHAR_BIT = %d\n", CHAR_BIT);
>>> printf("sizeof (unsigned) = %zu\n", sizeof (unsigned));
>>> printf("sizeof (struct has_bit_field) = %zu\n", sizeof (struct has_bit_field));
>>> printf("sizeof (struct has_unsigned_char) = %zu\n", sizeof (struct has_unsigned_char));
>>> }
>>>
>>> the output on my system is:
>>>
>>> CHAR_BIT = 8
>>> sizeof (unsigned) = 4
>>> sizeof (struct has_bit_field) = 4
>>> sizeof (struct has_unsigned_char) = 1
>>>
>>> What is the rationale for a bit-field forcing the structure to be
>>> expanded to 4 bytes, when the bit-field itself is only 1 bit?
>>> Why does a 1-bit bit-field for a bigger structure size than an 8-bit
>>> unsigned char member?
>>
>> It lets the /programmer/ make the choice.
>>
>> When I write "uint16_t x : 3;", I mean "Make a container field of size
>> and type uint16_t, and allocate 3 bits of it to x. If there is already
>> a container field of this type and size with enough free space just
>> before x, add it to the same container".
>
> struct eg {
> unsigned x : 3;
> unsigned : 16-3;
> };
>
> seems just as clear to me. Both rely on implementation-defined
> behaviour, but had gcc taken the other route, the programmer would still
> have the choice.
>
> It seems wrong for bit fields have an explicit type at all. What they
> need is only the signed/unsigned distinction for which there are already
> keywords.
>

If that had been the route implementations of bit-fields had taken, then
it would have worked to some extend - and we would have lived with it,
using (as now) explicit masking and shifting for cases where bit-fields
can't give the needed guarantees (perhaps due to portability needs).

However, reality is different. You can see an example in this godbolt
link <https://godbolt.org/z/3nT4nx7Gb>.

struct ea {
uint16_t x : 3;
uint16_t : 13;
};

struct eb {
uint16_t x : 3;
};

struct ec {
uint8_t x : 3;
uint16_t : 13;
};

struct eg {
unsigned x : 3;
unsigned : 16 - 3;
};

The standards say nothing about the required sizes, other than some
minimums. Real-world implementations make "struct eg" 32-bit (given
32-bit int), and the others all 16-bit.

If implementations were changed to make the size of "eg" the minimum
needed to support the bit-fields, it would break current code and
practice such as "struct eb" here. That alone means the idea of making
the containing struct have minimum size will never be put in the
standards. (And if there are current implementations unknown to me that
would make "struct eg" 16-bit here despite having 32-bit int, then that
would of course exclude the standards mandating the more common behaviour.)

Had "minimum size" been the commonly implemented behaviour, or required
by the standards, then it would have worked reasonably well. And as you
say, there would not be a need for a type for the bit-field, just
"signed" or "unsigned", or "_Bool".

It would not have allowed control of the access sizes for volatile
accesses. Though this is of course implementation-dependent, specifying
the type in the bit-field tells the compiler what size the programmer
wants. And it would not have allowed the use of enumeration types in
bit-field declarations. (Baring implementation-specific extensions,
enumeration types are generally indistinguishable from "int", but their
use can make code clearer and allow for better static checking.)

I don't disagree that the system you suggest could have worked, but
compiler implementers have gone a different route - one that I
personally think works better, based on the kind of coding I personally do.

Re: bit-fields of type unsigned long and unsigned long long

<sb4lvu$i73$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=277&group=comp.std.c#277

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 15:33:49 +0200
Organization: A noiseless patient Spider
Lines: 47
Message-ID: <sb4lvu$i73$1@dont-email.me>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me> <sb4j1a$dmn$1@solani.org>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 25 Jun 2021 13:33:50 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="e2dcdf334c1a7b567a02d744e0595df8";
logging-data="18659"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+m33aVe7sCEucHTI1SwCvQbEmAdFbU2i4="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.10.0
Cancel-Lock: sha1:nmDslE4fmNfS62DPDp31stfuVDY=
In-Reply-To: <sb4j1a$dmn$1@solani.org>
Content-Language: en-GB
 by: David Brown - Fri, 25 Jun 2021 13:33 UTC

On 25/06/2021 14:43, Philipp Klaus Krause wrote:
> Am 25.06.21 um 10:43 schrieb David Brown:
>
>>
>> As I see it, bit-fields are used for two main purposes.
>>
>> One is for structures internal to a program, in order to reduce space.
>> There are two typical reasons for that. You might have a small embedded
>> system with extremely small ram size (though these are getting less
>> common, and since they are very rarely used with anything newer than
>> C99, changes to the standard matter little there).
> If newer standards are rarely used for programming small embedded
> systems, is it because the standard might have been diverging from their
> requirements?
> Is it because newer standards take so much effort to implement that
> compilers other than GCC and clang lack the manpower to implement them
> timely?
> Is it because users follow a coding standard, such as MISRA, that takes
> a while to update for new C standards?
>

These are all valid reasons. I couldn't tell you the proportions here,
but I suspect you've covered the biggest points.

A lot of embedded developers are also very conservative - there is an
amazing amount still being written in C90.

And there is the question of what the newer C standards have given
embedded developers. C11 gave us atomics that don't work for embedded
systems, and threads that are useless even if embedded toolchain
developers bothered to make some kind of implementation for them.
_Generic is more complicated than most people want to see, and has
little use in practice. Static assertions are a wonderful idea - that's
why programmers in C90 and C99 already have them (using ugly macros
rather than a language feature, but they still work). Anonymous structs
and unions were already supported as extensions by many toolchains.

C17 gives nothing bug bug fixes.

Some emebedded programmers, such as myself, will use new standards when
they are supported by my tools and give some advantages.

But one of the most important points of C as a language is its
stability, consistency and backwards compatibility. It doesn't really
need changes, except perhaps to clarify some parts, simplify by removing
support for long-outdated systems, codify existing common practice, and
throw out old, dangerous and obsolete syntax.

Re: bit-fields of type unsigned long and unsigned long long

<875yy2ugks.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=278&group=comp.std.c#278

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 08:09:07 -0700
Organization: None to speak of
Lines: 107
Message-ID: <875yy2ugks.fsf@nosuchdomain.example.com>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me> <87a6neuxjo.fsf@nosuchdomain.example.com>
<sb4g65$4m4$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="e76a60976a03f7b22ccc859f0f74fb19";
logging-data="31742"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+v68UsNHP2GNsI8w/lCho1"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:ONtnkUmW5nYY/NFJMThzzy+qW68=
sha1:2ek7B//WmJ4g1Tli31wQFtUINZA=
 by: Keith Thompson - Fri, 25 Jun 2021 15:09 UTC

David Brown <david.brown@hesbynett.no> writes:
> On 25/06/2021 11:02, Keith Thompson wrote:
>> I don't see an answer to my question anywhere in there.
>>
>> To be perhaps a bit clearer, when I compile this program with gcc or
>> clang:
>>
>> #include <stdio.h>
>> #include <limits.h>
>> int main(void) {
>> struct has_bit_field {
>> unsigned bit_field : 1;
>> };
>> struct has_unsigned_char {
>> unsigned char uc;
>> };
>> printf("CHAR_BIT = %d\n", CHAR_BIT);
>> printf("sizeof (unsigned) = %zu\n", sizeof (unsigned));
>> printf("sizeof (struct has_bit_field) = %zu\n", sizeof (struct has_bit_field));
>> printf("sizeof (struct has_unsigned_char) = %zu\n", sizeof (struct has_unsigned_char));
>> }
>>
>> the output on my system is:
>>
>> CHAR_BIT = 8
>> sizeof (unsigned) = 4
>> sizeof (struct has_bit_field) = 4
>> sizeof (struct has_unsigned_char) = 1
>>
>> What is the rationale for a bit-field forcing the structure to be
>> expanded to 4 bytes, when the bit-field itself is only 1 bit?
>> Why does a 1-bit bit-field for a bigger structure size than an 8-bit
>> unsigned char member?
>
> It lets the /programmer/ make the choice.

I really don't understand that statement.

The way I *wish* bit-fields had been implemented is that a bit-field has
the specified size, and its declared type has no effect on the
structure's layout. *That* would let the programmer make the choice,
for example by defining an umnamed bit-field for padding if desired.
With that scheme, I can define an 8-bit structure containing two 4-bit
bit-fields. With the current common implementation, I can't (unless I
use a non-standard type for the bit-fields).

A 1-bit bit-field doesn't have an alignment requirement. Why should it
impose such a requirement on the containing structure?

> When I write "uint16_t x : 3;", I mean "Make a container field of size
> and type uint16_t, and allocate 3 bits of it to x. If there is already
> a container field of this type and size with enough free space just
> before x, add it to the same container".

Sure, that's how it works -- but nothing in the standard gives a clue
that that's what it should mean.

It just seems bizarre to me that the type of a bit-field has no effect
on the representation of the bit-field itself (other than signedness),
but it does affect the representation of the containing structure.

> That is the function I want bit-fields to have. That is what makes them
> useful in a wide range of use-cases. There are some situations where
> all you need is to say "x doesn't have to hold more than 3 bits of
> information, and I'd like the surrounding structure to be reasonably
> small". But often you want to have the control.

How exactly does the current scheme give the programmer more control?
If I want extra padding, I can add it myself. If I don't, I get it
anyway.

> Another situation where you need precise control for hardware registers
> is in the access sizes for volatile data (and hardware registers are
> usually accessed as volatile). Access size typically makes a /huge/
> difference in the hardware. If the bit-field "x" above is part of a
> volatile structure, then all reads and writes to it must be done using
> 16-bit accesses. (gcc had a bug for a while in their ARM port that
> meant a smaller access size would be used for smaller bit size of
> fields, giving 8-bit accesses for a 3 bit bit-field regardless of the
> declared type. This caused a lot of problems.)
>
> All in all, I want the type I give in the bit-field declaration to be
> used by the compiler. Otherwise, what's the point of having it at all?

But why should the type of a bit-field affect the layout of the
containing struct but not the representation of the bit-field itself?
Why impose an arbitrary restriction?

[snip]

> And therein, perhaps, is the biggest problem with bit-fields in C.
> Because there is virtually no guidance in the standards in this respect,
> people with different experiences, practices and needs for the language
> can have widely different expectations or assumptions about them. (I
> expect that in actual code you would not make such assumptions, since I
> believe you often have to write more portable code that avoids relying
> on implementation-defined behaviour.)

The way it seems to me is that, yes, bit-fields are underspecified, but
the common implementation imposes an arbitrary restriction that reduces
the programmer's control. There's nothing you can do with the existing
scheme that couldn't be done with the one I would have preferred.

--
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 */

Re: bit-fields of type unsigned long and unsigned long long

<871r8qufz0.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=279&group=comp.std.c#279

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 08:22:11 -0700
Organization: None to speak of
Lines: 59
Message-ID: <871r8qufz0.fsf@nosuchdomain.example.com>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me> <87a6neuxjo.fsf@nosuchdomain.example.com>
<sb4g65$4m4$1@dont-email.me> <8735t6no5f.fsf@bsb.me.uk>
<sb4l0o$v7u$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="e76a60976a03f7b22ccc859f0f74fb19";
logging-data="31742"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/37uquBoNkyNjuxqiLiUgh"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:Ek01x4op8lhCp9gfayoqJagwpOA=
sha1:KBDGXWAZfRxJcdiPhEBLASvnUT0=
 by: Keith Thompson - Fri, 25 Jun 2021 15:22 UTC

David Brown <david.brown@hesbynett.no> writes:
> On 25/06/2021 14:07, Ben Bacarisse wrote:
[...]
> If implementations were changed to make the size of "eg" the minimum
> needed to support the bit-fields, it would break current code and
> practice such as "struct eb" here. That alone means the idea of making
> the containing struct have minimum size will never be put in the
> standards. (And if there are current implementations unknown to me that
> would make "struct eg" 16-bit here despite having 32-bit int, then that
> would of course exclude the standards mandating the more common behaviour.)

Of course changing behavior that existing code depends on is not practical.

> Had "minimum size" been the commonly implemented behaviour, or required
> by the standards, then it would have worked reasonably well. And as you
> say, there would not be a need for a type for the bit-field, just
> "signed" or "unsigned", or "_Bool".
>
> It would not have allowed control of the access sizes for volatile
> accesses. Though this is of course implementation-dependent, specifying
> the type in the bit-field tells the compiler what size the programmer
> wants.

I don't follow. Tells the compiler the size of what? Not of the
bit-field itself. Can you give an example that illustrates your point
about volatile accesses?

> And it would not have allowed the use of enumeration types in
> bit-field declarations. (Baring implementation-specific extensions,
> enumeration types are generally indistinguishable from "int", but their
> use can make code clearer and allow for better static checking.)

Each enumeration type is compatible with some implementation-defined
integer type, not necessarily int. (Enumeration constants are of type
int.) But how would it not allow the use of enumeration bit-fields?
The current scheme, where the type affects the size of the struct, does
make that difficult (though a language feature to specify the underlying
type of an enum would make that easier). But something like this:
enum booool { no, maybe, probably, yes };
struct foo {
enum booool : 2;
unsigned : 6;
};
would make perfectly good sense under the scheme I would have preferred.

Unexpectedly, with gcc enum booool is 32 bits (it's compatible
with unsigned int) but struct foo is 8 bits.

> I don't disagree that the system you suggest could have worked, but
> compiler implementers have gone a different route - one that I
> personally think works better, based on the kind of coding I personally do.

Is there anything you can do with the current scheme that you couldn't
do with mine, perhaps with the addition of explicit padding?

--
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 */

Re: bit-fields of type unsigned long and unsigned long long

<sb4vsi$j9t$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=280&group=comp.std.c#280

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 18:22:42 +0200
Organization: A noiseless patient Spider
Lines: 132
Message-ID: <sb4vsi$j9t$1@dont-email.me>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me> <87a6neuxjo.fsf@nosuchdomain.example.com>
<sb4g65$4m4$1@dont-email.me> <8735t6no5f.fsf@bsb.me.uk>
<sb4l0o$v7u$1@dont-email.me> <871r8qufz0.fsf@nosuchdomain.example.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 25 Jun 2021 16:22:42 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="e2dcdf334c1a7b567a02d744e0595df8";
logging-data="19773"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19p3thjzASBIce7fPbZ6/KLBtZiNtEAHuU="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.10.0
Cancel-Lock: sha1:RzcjIvDtaJmNm5fH7XAlpp4aTr8=
In-Reply-To: <871r8qufz0.fsf@nosuchdomain.example.com>
Content-Language: en-GB
 by: David Brown - Fri, 25 Jun 2021 16:22 UTC

On 25/06/2021 17:22, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
>> On 25/06/2021 14:07, Ben Bacarisse wrote:
> [...]
>> If implementations were changed to make the size of "eg" the minimum
>> needed to support the bit-fields, it would break current code and
>> practice such as "struct eb" here. That alone means the idea of making
>> the containing struct have minimum size will never be put in the
>> standards. (And if there are current implementations unknown to me that
>> would make "struct eg" 16-bit here despite having 32-bit int, then that
>> would of course exclude the standards mandating the more common behaviour.)
>
> Of course changing behavior that existing code depends on is not practical.
>
>> Had "minimum size" been the commonly implemented behaviour, or required
>> by the standards, then it would have worked reasonably well. And as you
>> say, there would not be a need for a type for the bit-field, just
>> "signed" or "unsigned", or "_Bool".
>>
>> It would not have allowed control of the access sizes for volatile
>> accesses. Though this is of course implementation-dependent, specifying
>> the type in the bit-field tells the compiler what size the programmer
>> wants.
>
> I don't follow. Tells the compiler the size of what? Not of the
> bit-field itself. Can you give an example that illustrates your point
> about volatile accesses?

I did, with the godbolt link that you snipped. (If you don't like
godbolt links, I can paste it into a post, but the link makes it easy to
see the code and the generated results for whatever processor you are
familiar with.)

Another relevant link would be
<https://github.com/ARM-software/abi-aa/blob/f52e1ad3f81254497a83578dc102f6aac89e52d0/aapcs32/aapcs32.rst#8175volatile-bit-fields--preserving-number-and-width-of-container-accesses>

This is part of the ABI for ARM, which describes how volatile bit-field
access should work on that target.

You might not be very familiar with low-level coding and hardware access
(most programmers are not). Hardware is usually memory-mapped these
days. So if you are making a driver for, say, a UART (an old-fashioned
serial port) there will be specific memory addresses for a "receive"
port, a "transmit" port, for control registers for setting the baud
rate, status registers for flags, etc. A common way to handle this is
to make a struct built up from uintN_t fixed-size types and bit-fields
for the control and status fields. Your code must be precise in how it
accesses these - reading and writing registers can trigger actions. For
example, a write to the transmit register might send out a character on
the bus. Reading from the receive register might change some flags and
collect the next character from an input buffer. So you must not access
neighbouring registers unintentionally. Equally, a register might
require a 16-bit or 32-bit access to work correctly, and reading or
writing by byte will fail. You must have full control of exactly what
sizes you are using for the accesses as well as the ordering of them.

This kind of thing is, of course, implementation dependent and outside
the scope of the C standards. But people program such things in C and
specifying the exact type for the fields is how you control the exact
size of the accesses.

>
>> And it would not have allowed the use of enumeration types in
>> bit-field declarations. (Baring implementation-specific extensions,
>> enumeration types are generally indistinguishable from "int", but their
>> use can make code clearer and allow for better static checking.)
>
> Each enumeration type is compatible with some implementation-defined
> integer type, not necessarily int. (Enumeration constants are of type
> int.) But how would it not allow the use of enumeration bit-fields?

Ben's suggestion (in the sense of what he thinks would have been a good
choice for the language, rather than how he would like the standards to
be changed) was to have only "signed" or "unsigned" as the type for
bit-fields. That rules out enumeration types.

> The current scheme, where the type affects the size of the struct, does
> make that difficult (though a language feature to specify the underlying
> type of an enum would make that easier). But something like this:
> enum booool { no, maybe, probably, yes };

(Reminds me of <https://thedailywtf.com/articles/What_Is_Truth_0x3f_>)

> struct foo {
> enum booool : 2;
> unsigned : 6;
> };
> would make perfectly good sense under the scheme I would have preferred.

Yes, that would be possible in your scheme (but see next comment).

>
> Unexpectedly, with gcc enum booool is 32 bits (it's compatible
> with unsigned int) but struct foo is 8 bits.

That is not /entirely/ unexpected. You have no named fields in the
struct, which I believe is a constraint error in C (it triggers a
-Wpedantic warning in gcc). The sizeof of an empty struct is usually
given as 1.

If you have "enum booool b : 2;" instead, the struct has size 32 bits.
That's not always what I would like, but it is consistent with the size
of the enumeration type (given by the ABI). And for those that want
tighter control and are happy with extensions, gcc's "packed" attribute
lets you make smaller enumeration types. (Or you can use C++'s scoped
enums, that can have their underlying type specified. It might be nice
for C to copy that feature.)

>
>> I don't disagree that the system you suggest could have worked, but
>> compiler implementers have gone a different route - one that I
>> personally think works better, based on the kind of coding I personally do.
>
> Is there anything you can do with the current scheme that you couldn't
> do with mine, perhaps with the addition of explicit padding?
>

Yes - I can't tell the compiler the size for volatile accesses.

Apart from that, your scheme could work. But to me, it would be a step
backwards in clarity of code. It's like suggesting C could be
simplified by removing the binary minus operator. After all, you can
write "a - b" as "a + -b". It's true, but it is not helpful to the
language.

If I want things to be of particular sizes and alignments, I use clear
fixed-size types. I don't have to figure out counts of padding bits and
add them in. The current scheme - as supported by compilers today -
lets you write code in a manner that gives a closer correspondence
between the text you write and results you get, for low level code.

Re: bit-fields of type unsigned long and unsigned long long

<87r1gpn79q.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=281&group=comp.std.c#281

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 19:12:01 +0100
Organization: A noiseless patient Spider
Lines: 82
Message-ID: <87r1gpn79q.fsf@bsb.me.uk>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me> <87a6neuxjo.fsf@nosuchdomain.example.com>
<sb4g65$4m4$1@dont-email.me> <8735t6no5f.fsf@bsb.me.uk>
<sb4l0o$v7u$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="c9051376ae85fc2e6ee14100b71f4598";
logging-data="324"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19gKwNjJtrf8IEe5x6Jg/j0PKcHWihmq/8="
Cancel-Lock: sha1:Y/kmgot6PN/JAlTJ43F1Fjz8Ohg=
sha1:Pkz0V9BNRdcEtT3NpIFx7/NuqcI=
X-BSB-Auth: 1.2d99a5914a85fed69a91.20210625191201BST.87r1gpn79q.fsf@bsb.me.uk
 by: Ben Bacarisse - Fri, 25 Jun 2021 18:12 UTC

David Brown <david.brown@hesbynett.no> writes:

> On 25/06/2021 14:07, Ben Bacarisse wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>
>>> On 25/06/2021 11:02, Keith Thompson wrote:
>>>
>>>>
>>>> I don't see an answer to my question anywhere in there.
>>>>
>>>> To be perhaps a bit clearer, when I compile this program with gcc or
>>>> clang:
>>>>
>>>> #include <stdio.h>
>>>> #include <limits.h>
>>>> int main(void) {
>>>> struct has_bit_field {
>>>> unsigned bit_field : 1;
>>>> };
>>>> struct has_unsigned_char {
>>>> unsigned char uc;
>>>> };
>>>> printf("CHAR_BIT = %d\n", CHAR_BIT);
>>>> printf("sizeof (unsigned) = %zu\n", sizeof (unsigned));
>>>> printf("sizeof (struct has_bit_field) = %zu\n", sizeof (struct has_bit_field));
>>>> printf("sizeof (struct has_unsigned_char) = %zu\n", sizeof (struct has_unsigned_char));
>>>> }
>>>>
>>>> the output on my system is:
>>>>
>>>> CHAR_BIT = 8
>>>> sizeof (unsigned) = 4
>>>> sizeof (struct has_bit_field) = 4
>>>> sizeof (struct has_unsigned_char) = 1
>>>>
>>>> What is the rationale for a bit-field forcing the structure to be
>>>> expanded to 4 bytes, when the bit-field itself is only 1 bit?
>>>> Why does a 1-bit bit-field for a bigger structure size than an 8-bit
>>>> unsigned char member?
>>>
>>> It lets the /programmer/ make the choice.
>>>
>>> When I write "uint16_t x : 3;", I mean "Make a container field of size
>>> and type uint16_t, and allocate 3 bits of it to x. If there is already
>>> a container field of this type and size with enough free space just
>>> before x, add it to the same container".
>>
>> struct eg {
>> unsigned x : 3;
>> unsigned : 16-3;
>> };
>>
>> seems just as clear to me. Both rely on implementation-defined
>> behaviour, but had gcc taken the other route, the programmer would still
>> have the choice.
>>
>> It seems wrong for bit fields have an explicit type at all. What they
>> need is only the signed/unsigned distinction for which there are already
>> keywords.
>>
>
> If that had been the route implementations of bit-fields had taken,
> ...

Yes, I said exactly that. Both routes offer what you gave as the
justification for one.

<cut>
> Had "minimum size" been the commonly implemented behaviour, or required
> by the standards, then it would have worked reasonably well. And as you
> say, there would not be a need for a type for the bit-field, just
> "signed" or "unsigned", or "_Bool".
>
> It would not have allowed control of the access sizes for volatile
> accesses.

I don't know what you mean here. I know what all the words mean, but I
don't know sort of control you mean nor how one implementation choice
would prevent it.

--
Ben.

Re: bit-fields of type unsigned long and unsigned long long

<87sg15u1sr.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=282&group=comp.std.c#282

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Fri, 25 Jun 2021 13:28:20 -0700
Organization: None to speak of
Lines: 174
Message-ID: <87sg15u1sr.fsf@nosuchdomain.example.com>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me> <87a6neuxjo.fsf@nosuchdomain.example.com>
<sb4g65$4m4$1@dont-email.me> <8735t6no5f.fsf@bsb.me.uk>
<sb4l0o$v7u$1@dont-email.me> <871r8qufz0.fsf@nosuchdomain.example.com>
<sb4vsi$j9t$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="e76a60976a03f7b22ccc859f0f74fb19";
logging-data="7602"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/A/eIha5ZrwGgImjsHdh78"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:dBskKtKU3AtZnLmvB1UDqAFcavc=
sha1:Jsb2D52qy9yyElme7C6hI7SPkmU=
 by: Keith Thompson - Fri, 25 Jun 2021 20:28 UTC

David Brown <david.brown@hesbynett.no> writes:
> On 25/06/2021 17:22, Keith Thompson wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>> On 25/06/2021 14:07, Ben Bacarisse wrote:
>> [...]
>>> If implementations were changed to make the size of "eg" the minimum
>>> needed to support the bit-fields, it would break current code and
>>> practice such as "struct eb" here. That alone means the idea of making
>>> the containing struct have minimum size will never be put in the
>>> standards. (And if there are current implementations unknown to me that
>>> would make "struct eg" 16-bit here despite having 32-bit int, then that
>>> would of course exclude the standards mandating the more common behaviour.)
>>
>> Of course changing behavior that existing code depends on is not practical.
>>
>>> Had "minimum size" been the commonly implemented behaviour, or required
>>> by the standards, then it would have worked reasonably well. And as you
>>> say, there would not be a need for a type for the bit-field, just
>>> "signed" or "unsigned", or "_Bool".
>>>
>>> It would not have allowed control of the access sizes for volatile
>>> accesses. Though this is of course implementation-dependent, specifying
>>> the type in the bit-field tells the compiler what size the programmer
>>> wants.
>>
>> I don't follow. Tells the compiler the size of what? Not of the
>> bit-field itself. Can you give an example that illustrates your point
>> about volatile accesses?
>
> I did, with the godbolt link that you snipped. (If you don't like
> godbolt links, I can paste it into a post, but the link makes it easy to
> see the code and the generated results for whatever processor you are
> familiar with.)

My mistake. I saw the link followed by some code, and incorrectly
assumed the link just had the code you posted, so I didn't follow it.
I'll look at it later.

> Another relevant link would be
> <https://github.com/ARM-software/abi-aa/blob/f52e1ad3f81254497a83578dc102f6aac89e52d0/aapcs32/aapcs32.rst#8175volatile-bit-fields--preserving-number-and-width-of-container-accesses>
>
> This is part of the ABI for ARM, which describes how volatile bit-field
> access should work on that target.
>
> You might not be very familiar with low-level coding and hardware access
> (most programmers are not). Hardware is usually memory-mapped these
> days. So if you are making a driver for, say, a UART (an old-fashioned
> serial port) there will be specific memory addresses for a "receive"
> port, a "transmit" port, for control registers for setting the baud
> rate, status registers for flags, etc. A common way to handle this is
> to make a struct built up from uintN_t fixed-size types and bit-fields
> for the control and status fields. Your code must be precise in how it
> accesses these - reading and writing registers can trigger actions. For
> example, a write to the transmit register might send out a character on
> the bus. Reading from the receive register might change some flags and
> collect the next character from an input buffer. So you must not access
> neighbouring registers unintentionally. Equally, a register might
> require a 16-bit or 32-bit access to work correctly, and reading or
> writing by byte will fail. You must have full control of exactly what
> sizes you are using for the accesses as well as the ordering of them.
>
> This kind of thing is, of course, implementation dependent and outside
> the scope of the C standards. But people program such things in C and
> specifying the exact type for the fields is how you control the exact
> size of the accesses.
>
>>> And it would not have allowed the use of enumeration types in
>>> bit-field declarations. (Baring implementation-specific extensions,
>>> enumeration types are generally indistinguishable from "int", but their
>>> use can make code clearer and allow for better static checking.)
>>
>> Each enumeration type is compatible with some implementation-defined
>> integer type, not necessarily int. (Enumeration constants are of type
>> int.) But how would it not allow the use of enumeration bit-fields?
>
> Ben's suggestion (in the sense of what he thinks would have been a good
> choice for the language, rather than how he would like the standards to
> be changed) was to have only "signed" or "unsigned" as the type for
> bit-fields. That rules out enumeration types.
>
>> The current scheme, where the type affects the size of the struct, does
>> make that difficult (though a language feature to specify the underlying
>> type of an enum would make that easier). But something like this:
>> enum booool { no, maybe, probably, yes };
>
> (Reminds me of <https://thedailywtf.com/articles/What_Is_Truth_0x3f_>)

Hey, at least I made "no" equal to 0.

>> struct foo {
>> enum booool : 2;
>> unsigned : 6;
>> };
>> would make perfectly good sense under the scheme I would have preferred.
>
>
> Yes, that would be possible in your scheme (but see next comment).
>
>>
>> Unexpectedly, with gcc enum booool is 32 bits (it's compatible
>> with unsigned int) but struct foo is 8 bits.
>
> That is not /entirely/ unexpected. You have no named fields in the
> struct, which I believe is a constraint error in C (it triggers a
> -Wpedantic warning in gcc). The sizeof of an empty struct is usually
> given as 1.

The lack of named fields was just an oversight.

> If you have "enum booool b : 2;" instead, the struct has size 32 bits.
> That's not always what I would like, but it is consistent with the size
> of the enumeration type (given by the ABI). And for those that want
> tighter control and are happy with extensions, gcc's "packed" attribute
> lets you make smaller enumeration types. (Or you can use C++'s scoped
> enums, that can have their underlying type specified. It might be nice
> for C to copy that feature.)

Hmm. The idea that making a bit-field anonymous, without changing its
type or size, affects the layout of the structure seems weird and
arbitrary to me, even more so than what I've been ranting about
previously in this thread.

>>> I don't disagree that the system you suggest could have worked, but
>>> compiler implementers have gone a different route - one that I
>>> personally think works better, based on the kind of coding I personally do.
>>
>> Is there anything you can do with the current scheme that you couldn't
>> do with mine, perhaps with the addition of explicit padding?
>
> Yes - I can't tell the compiler the size for volatile accesses.
>
> Apart from that, your scheme could work. But to me, it would be a step
> backwards in clarity of code. It's like suggesting C could be
> simplified by removing the binary minus operator. After all, you can
> write "a - b" as "a + -b". It's true, but it is not helpful to the
> language.
>
> If I want things to be of particular sizes and alignments, I use clear
> fixed-size types. I don't have to figure out counts of padding bits and
> add them in. The current scheme - as supported by compilers today -
> lets you write code in a manner that gives a closer correspondence
> between the text you write and results you get, for low level code.

I'll look into the volatile stuff. But again, the idea that the type of
a bit-field *doesn't* affect the representation of the bit-field itself
but *does* affect the representation of the enclosing structure just
feels arbitrary and weird to me. And it's quite possible that I've
ranted about it enough.

....

After writing the above, I did a Google search for "struct bit-field
affects size". I found this post on Stack Overflow from 8 years ago:
https://stackoverflow.com/q/15980589/827263
The wording of the question seemed familiar. I figured out why when I
saw my own name at the bottom of the post. 8-)}

Following the links, there's some discussion of bit-fields in the
System V ABI for i386
http://www.sco.com/developers/devspecs/abi386-4.pdf

Summary: The idea that the declared type of a bit-field should affect
the size of the containing structure appears to be intuitively obvious
to some people (including, apparently, the authors of the i386 ABI), but
completely out of left field to others (at least to me). I have yet to
figure out why my intuition on this point differs so much from at least
some other people's. And I think I'm going to drop it unless someone
has some new insights to offer. Meanwhile, I rarely use bit-fields, and
when I do I'll be aware of how they work in practice.


Click here to read the complete article
Re: bit-fields of type unsigned long and unsigned long long

<P8CdnRiV8v4RVXn9nZ2dnUU78R3NnZ2d@giganews.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=283&group=comp.std.c#283

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!aioe.org!feeder1.feed.usenet.farm!feed.usenet.farm!border1.nntp.ams1.giganews.com!nntp.giganews.com!buffer1.nntp.ams1.giganews.com!news.giganews.com.POSTED!not-for-mail
NNTP-Posting-Date: Tue, 06 Jul 2021 16:18:04 -0500
Subject: Re: bit-fields of type unsigned long and unsigned long long
Newsgroups: comp.std.c
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com>
<sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com>
<sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com>
<sb44vv$frb$1@dont-email.me> <sb4j1a$dmn$1@solani.org>
From: jb-use...@wisemo.com.invalid (Jakob Bohm)
Organization: WiseMo A/S
Date: Tue, 6 Jul 2021 23:18:04 +0200
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:4.8) Goanna/20210402
Interlink/52.9.7762
MIME-Version: 1.0
In-Reply-To: <sb4j1a$dmn$1@solani.org>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 8bit
Message-ID: <P8CdnRiV8v4RVXn9nZ2dnUU78R3NnZ2d@giganews.com>
Lines: 71
X-Usenet-Provider: http://www.giganews.com
X-Trace: sv3-48ZQJYrRFp3LHCD0uoVBucptLX3z8Hkp8eMHfihfhv5BFeUxu15qYPAmMRFkAvNpx45n9X1sN/47zN9!f9Tw7tjZDT/ohWDvphUr+XpEruvRkBWoFUN5NZh/sAa5Ifh76b5vAw9rUZFEmlcggRgDElWjrUQ=
X-Complaints-To: abuse@giganews.com
X-DMCA-Notifications: http://www.giganews.com/info/dmca.html
X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers
X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly
X-Postfilter: 1.3.40
X-Original-Bytes: 4799
 by: Jakob Bohm - Tue, 6 Jul 2021 21:18 UTC

On 2021-06-25 14:43, Philipp Klaus Krause wrote:
> Am 25.06.21 um 10:43 schrieb David Brown:
>
>>
>> As I see it, bit-fields are used for two main purposes.
>>
>> One is for structures internal to a program, in order to reduce space.
>> There are two typical reasons for that. You might have a small embedded
>> system with extremely small ram size (though these are getting less
>> common, and since they are very rarely used with anything newer than
>> C99, changes to the standard matter little there).
> If newer standards are rarely used for programming small embedded
> systems, is it because the standard might have been diverging from their
> requirements?
> Is it because newer standards take so much effort to implement that
> compilers other than GCC and clang lack the manpower to implement them
> timely?
> Is it because users follow a coding standard, such as MISRA, that takes
> a while to update for new C standards?
>

Besides what Mr. Krause mentioned, a major reason is that many
embedded platforms are stuck with whichever actual compiler
implementation shipped with the first release of that platform.

Any new compilers tend to emulate that historic compiler extremely
closely in order to get identical or very closely equivalent
binaries from existing source code. And programmers that care
tend to read up on which language "enhancements" will make their
code incompatible with existing toolchains and smaller/cheaper/older
platform versions.

This essentially locks each platform family to that historic
compiler and its idiosyncrasies.

However newly created embedded platforms such as embedded RISC-VI
or any new bit-sliced utility processor for FPGA projects would
get frozen to whatever the commonly implemented language will be
when that platform is created. This makes it worthwhile to discuss
future improvements to the language for deeply embedded systems.

A language aspect that will be useful even for existing platforms is
a standard, easily backported, way to tell reusable code which language
implementation alternatives are in effect when compiling the portable
code with any old toolchain. Basically a supplement to <limits.h>
that covers all the stuff currently only left to "read the
implementation defined features document hopefully provided by your
vendor" .

Something that will allow a strictly conformant program or translation
unit to actively use whichever syntax that historic compiler uses for
things like "place this bit field at the most significant bit of the
second byte" or "allow +1 to set this bit field to 1" or what bit
encoding is used for signed ints (2s complement, 1s complement,
sign+magnitude, etc.)

Every implementation-defined language aspect needs a standard define
indicating which alternative was chosen, with values for each common or
historic choice, and a (common) rule for how to add yet-to-be-invented
choices in a forward compatible manner. But turning it into a formal
workable proposal is a major exercise.

Enjoy

Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded

Re: bit-fields of type unsigned long and unsigned long long

<86r1g688kk.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=287&group=comp.std.c#287

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Sat, 10 Jul 2021 08:58:19 -0700
Organization: A noiseless patient Spider
Lines: 11
Message-ID: <86r1g688kk.fsf@linuxsc.com>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com> <sb1hni$5t2$1@dont-email.me> <878s2zw30y.fsf@nosuchdomain.example.com> <sb2see$t4s$1@dont-email.me> <87v962vrh3.fsf@nosuchdomain.example.com> <sb44vv$frb$1@dont-email.me> <87a6neuxjo.fsf@nosuchdomain.example.com> <sb4g65$4m4$1@dont-email.me> <8735t6no5f.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: reader02.eternal-september.org; posting-host="e13df7ffef68eec8a0b0a92150d2f271";
logging-data="2695"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18lluVenLNdXH3n3hHa9DgPH/9s94WZGbY="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:Uej9ho3rPYtdUaR/MoluREKghns=
sha1:CoNNHKKsUCRxh0JqGgpE8vrjddk=
 by: Tim Rentsch - Sat, 10 Jul 2021 15:58 UTC

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

[...]

> It seems wrong for bit fields have an explicit type at all. What they
> need is only the signed/unsigned distinction for which there are already
> keywords.

I was about to say that I completely agree, but there is an
important exception, namely _Bool. A bitfield of type _Bool
has different semantics than a bitfield of type unsigned :1.

Re: bit-fields of type unsigned long and unsigned long long

<86mtqu87um.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=288&group=comp.std.c#288

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Sat, 10 Jul 2021 09:13:53 -0700
Organization: A noiseless patient Spider
Lines: 42
Message-ID: <86mtqu87um.fsf@linuxsc.com>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com> <savtku$6a6$1@solani.org> <8635t7ayki.fsf@linuxsc.com> <87zgvfukwa.fsf@nosuchdomain.example.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: reader02.eternal-september.org; posting-host="e13df7ffef68eec8a0b0a92150d2f271";
logging-data="2695"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+m7c1oyAUrEkunsH34bJKzmlg6EBwr638="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:otHYMMnTGiwG4qugWL0ah8KzJJg=
sha1:J2wYdDxOsYLw/EpuSNKrWghKVSE=
 by: Tim Rentsch - Sat, 10 Jul 2021 16:13 UTC

Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Philipp Klaus Krause <pkk@spth.de> writes:
>>
>>> Am 23.06.21 um 19:53 schrieb Tim Rentsch:
>>>
>>>> Bit-fields of types signed and unsigned may use widths up to the
>>>> widths of intmax_t and uintmax_t, respectively.
>>>
>>> WG14 usually doesn't like to use the same syntax as C++ but with a
>>> different meaning.
>>> AFAIK, in C++, you can have an int bit-field wider than int (or whatever
>>> else the type is), but the upper bits then are padding bits.
>>
>> The obvious answer is to ask the C++ committee to change their
>> silly rule. And if they don't want to change it, just ignore it;
>> the C++ rule is already incompatible with C, now it will just be
>> incompatible in a different way. The gap between C and C++ has
>> increased to the point where they should be treated as separate
>> and independent languages.
>
> It's no more incompatible than any other C++ feature that doesn't exist
> in C. A program that defines a bit field with a length that exceeds the
> width of the type is a constraint violation in C, and valid in C++.

I don't know what point you're trying to make here. How it works
in C++ is different from how it works in C. That the C standard
deems it a constraint violation to me seems irrelevant. The
important point is that the behaviors in the two cases aren't
the same.

> On the other hand, I agree that the C++ rule *seems* silly. I wonder
> what the rationale is. (The earliest reference to the rule that I found
> is in the C++ 1998 standard.)
>
> It would be nice to avoid *gratuitous* incompatibilities between C and
> C++.

It would be even nicer in this particular case if C++ changed
its silly rule to the rule I suggested for C.

Re: bit-fields of type unsigned long and unsigned long long

<86im1i87e4.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=289&group=comp.std.c#289

  copy link   Newsgroups: comp.std.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.std.c
Subject: Re: bit-fields of type unsigned long and unsigned long long
Date: Sat, 10 Jul 2021 09:23:47 -0700
Organization: A noiseless patient Spider
Lines: 23
Message-ID: <86im1i87e4.fsf@linuxsc.com>
References: <sastag$a33$1@solani.org> <86fsx8bh88.fsf@linuxsc.com> <savtku$6a6$1@solani.org> <8635t7ayki.fsf@linuxsc.com> <sb2p2o$mpq$1@solani.org>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: reader02.eternal-september.org; posting-host="e13df7ffef68eec8a0b0a92150d2f271";
logging-data="2695"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18FPG4tjwYYWD2OBtYn2mmbGu5xPS3Vbug="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:fdkcNLkRA2vgvfPg6OnDIRv6xQQ=
sha1:FaJE8ysETK8RIUQuevmoq2oI4G0=
 by: Tim Rentsch - Sat, 10 Jul 2021 16:23 UTC

Philipp Klaus Krause <pkk@spth.de> writes:

> Am 24.06.21 um 20:48 schrieb Tim Rentsch:
>
>> The obvious answer is to ask the C++ committee to change their
>> silly rule. And if they don't want to change it, just ignore it;
>> the C++ rule is already incompatible with C, now it will just be
>> incompatible in a different way. The gap between C and C++ has
>> increased to the point where they should be treated as separate
>> and independent languages.
>
> WG14 and WG21 try to keep the common subset compatible, especially if it
> is something that might appear in headers (for other code this matters
> less - after all non-header source is usually either C or C++, but
> headers are commonly shared).
> And bit-fields are in struct declarations which are often in headers.

If WG21 is interested in keeping the common subset compatible, then
they should change their silly rule to something more sensible,
such as the rule I suggested. ISTM that the C++ folks always want
the C standard to change to accommodate them, but aren't all that
interested in reciprocating. It's time for that to change. And
if they aren't willing to change, screw 'em. You may quote me.

Pages:12
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor