• Re: Microcontroller software stacks

    From Tim Rentsch@3:633/10 to All on Fri Aug 14 12:51:32 2026
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value [...] */
    uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum value [...] */
    uint32_t cimin : 8; /**< R/W/H - COMINIT minimum value [...] */
    uint32_t cimax : 8; /**< R/W/H - COMINIT maximum value [...] */
    #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields type.
    I would just use unsigned, which is just as sure to work as intended,
    isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification. Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u. My question is only about the type used for the bitfields. Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    There are other hardware registers in our implementation of the SATA controller that are defined as 64-bit registers, for those we use
    uint64_t (rather than relying on 'unsigned long' for 64-bit linux
    or 'unsigned long long' for 32-bit OS - and this code was designed
    to be compiled for both 32-bit and 64-bit targets originally).

    Sure, for the non-bitfield member. My question is only about
    (unsigned) bitfields all of width 8 or less.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Sat Aug 15 05:02:06 2026
    On 15/08/2026 3:51 AM, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value [...] */ >>>> uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum value [...] */ >>>> uint32_t cimin : 8; /**< R/W/H - COMINIT minimum value [...] */ >>>> uint32_t cimax : 8; /**< R/W/H - COMINIT maximum value [...] */ >>>> #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields type.
    I would just use unsigned, which is just as sure to work as intended,
    isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification. Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u. My question is only about the type used for the bitfields. Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    Yes, people still code real mode DOS for fun and amusement. Not to
    mention boot strapping code for /real operating systems/, for some value
    of /real/.

    On 6502, int is 16bit, I believe, for reasons. And I also believe it
    makes total sense to keep int 16bit on a 68000.


    There are other hardware registers in our implementation of the SATA
    controller that are defined as 64-bit registers, for those we use
    uint64_t (rather than relying on 'unsigned long' for 64-bit linux
    or 'unsigned long long' for 32-bit OS - and this code was designed
    to be compiled for both 32-bit and 64-bit targets originally).

    Sure, for the non-bitfield member. My question is only about
    (unsigned) bitfields all of width 8 or less.

    I'm ignorant of the prior discussion, so I'll stop now; happy retro-
    coding!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Fri Aug 14 14:06:55 2026
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    [...]
    I understand the motivation for using uint32_t for the union member
    u. My question is only about the type used for the bitfields. Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    On platforms where unsigned int is 32 bits, I'd be very surprised
    if it made any difference. If unsigned it is, say, 16 or 64 bits,
    it can make a difference.

    As I wrote here a while ago, "Implementions commonly use the declared
    type of a bit-field to affect the layout, not necessarily of the
    bit-field itself, but of the containing structure." This was in
    a thread with the subject "Storage needed when there are bit-field
    members", in a followup to your post a few days after the article
    to which you've just replied.

    On the other hand, the standard only requires support for
    bitfields of declared types int, signed int, unsigned int, and bool
    (and bit-precise integer types in C23 and later); a conforming
    implementation might not support bit-fields of type uint32_t.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Fri Aug 14 21:42:38 2026
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value [...] */
    uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum value [...] */
    uint32_t cimin : 8; /**< R/W/H - COMINIT minimum value [...] */
    uint32_t cimax : 8; /**< R/W/H - COMINIT maximum value [...] */
    #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields type.
    I would just use unsigned, which is just as sure to work as intended,
    isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification. Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u. My question is only about the type used for the bitfields. Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    I haven't canvassed all the available platforms, and don't have
    any desire so to do. In my opinion, using the same type for the
    bitfield members as was used for the corresponding union
    element is simply logical. If we declare the integer part
    of the union as uint64_t, we use the same time for the
    bitfields (and yes, we could have used unsigned long
    (or unsigned long long on the micky OS) - uint64_t
    is less typing.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From bart@3:633/10 to All on Sat Aug 15 01:18:05 2026
    On 14/08/2026 22:02, Johann 'Myrkraverk' Oskarsson wrote:
    On 15/08/2026 3:51 AM, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah.ÿ This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    ÿÿ uint32_t u;
    ÿÿ struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    ÿÿÿÿ uint32_t weÿÿÿÿ :ÿ 1; /**< R/W/H - Write enable. */
    ÿÿÿÿ uint32_t cwminÿ :ÿ 7; /**< R/W/H - COMWAKE minimum value [...] */ >>>>> ÿÿÿÿ uint32_t cwmaxÿ :ÿ 8; /**< R/W/H - COMWAKE maximum value [...] */ >>>>> ÿÿÿÿ uint32_t ciminÿ :ÿ 8; /**< R/W/H - COMINIT minimum value [...] */ >>>>> ÿÿÿÿ uint32_t cimaxÿ :ÿ 8; /**< R/W/H - COMINIT maximum value [...] */ >>>>> #else
    ÿÿÿÿ uint32_t cimaxÿ :ÿ 8;
    ÿÿÿÿ uint32_t ciminÿ :ÿ 8;
    ÿÿÿÿ uint32_t cwmaxÿ :ÿ 8;
    ÿÿÿÿ uint32_t cwminÿ :ÿ 7;
    ÿÿÿÿ uint32_t weÿÿÿÿ :ÿ 1;
    #endif
    ÿÿ } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields type.
    I would just use unsigned, which is just as sure to work as intended,
    isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification.ÿ Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u.ÿ My question is only about the type used for the bitfields.ÿ Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    Yes, people still code real mode DOS for fun and amusement.ÿ Not to
    mention boot strapping code for /real operating systems/, for some value
    of /real/.

    On 6502, int is 16bit, I believe, for reasons.ÿ And I also believe it
    makes total sense to keep int 16bit on a 68000.


    WTF are you on about? If you're an actual human then I suggest getting
    some help. If not then where the hell does all this bilge come from?


    There are other hardware registers in our implementation of the SATA
    controller that are defined as 64-bit registers, for those we use
    uint64_t (rather than relying on 'unsigned long' for 64-bit linux
    or 'unsigned long long' for 32-bit OS - and this code was designed
    to be compiled for both 32-bit and 64-bit targets originally).

    Sure, for the non-bitfield member.ÿ My question is only about
    (unsigned) bitfields all of width 8 or less.

    I'm ignorant of the prior discussion, so I'll stop now; happy retro-
    coding!

    'Happy' - OK, CMT has finally convinced me!

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Sat Aug 15 22:13:03 2026
    On Fri, 14 Aug 2026 21:42:38 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value
    [...] */ uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum
    value [...] */ uint32_t cimin : 8; /**< R/W/H - COMINIT
    minimum value [...] */ uint32_t cimax : 8; /**< R/W/H -
    COMINIT maximum value [...] */ #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields
    type. I would just use unsigned, which is just as sure to work as
    intended, isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification. Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u. My question is only about the type used for the bitfields. Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    I haven't canvassed all the available platforms, and don't have
    any desire so to do. In my opinion, using the same type for the
    bitfield members as was used for the corresponding union
    element is simply logical. If we declare the integer part
    of the union as uint64_t, we use the same time for the
    bitfields (and yes, we could have used unsigned long
    (or unsigned long long on the micky OS) - uint64_t
    is less typing.


    Why not plain 'unsigned' ?







    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Sat Aug 15 19:39:54 2026
    Michael S <already5chosen@yahoo.com> writes:
    On Fri, 14 Aug 2026 21:42:38 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value
    [...] */ uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum
    value [...] */ uint32_t cimin : 8; /**< R/W/H - COMINIT
    minimum value [...] */ uint32_t cimax : 8; /**< R/W/H -
    COMINIT maximum value [...] */ #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields
    type. I would just use unsigned, which is just as sure to work as
    intended, isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification. Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u. My question is only about the type used for the bitfields. Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    I haven't canvassed all the available platforms, and don't have
    any desire so to do. In my opinion, using the same type for the
    bitfield members as was used for the corresponding union
    element is simply logical. If we declare the integer part
    of the union as uint64_t, we use the same time for the
    bitfields (and yes, we could have used unsigned long
    (or unsigned long long on the micky OS) - uint64_t
    is less typing.


    Why not plain 'unsigned' ?


    Did you not read the paragraph you are responding to?

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Sat Aug 15 23:22:15 2026
    On Sat, 15 Aug 2026 19:39:54 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Michael S <already5chosen@yahoo.com> writes:
    On Fri, 14 Aug 2026 21:42:38 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one
    of the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value
    [...] */ uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum
    value [...] */ uint32_t cimin : 8; /**< R/W/H - COMINIT
    minimum value [...] */ uint32_t cimax : 8; /**< R/W/H -
    COMINIT maximum value [...] */ #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields
    type. I would just use unsigned, which is just as sure to work
    as intended, isn't it?

    The SATA hardware register is defined as a 32-bit register in
    the SATA specification. Therefore we explicitly declare it as
    such.

    I understand the motivation for using uint32_t for the union
    member u. My question is only about the type used for the
    bitfields. Do you know of any platform, or even suspect that
    there might be a platform, where using 'unsigned' rather than
    'uint32_t' for the type of the bitfields makes any difference at
    all?

    I haven't canvassed all the available platforms, and don't have
    any desire so to do. In my opinion, using the same type for the
    bitfield members as was used for the corresponding union
    element is simply logical. If we declare the integer part
    of the union as uint64_t, we use the same time for the
    bitfields (and yes, we could have used unsigned long
    (or unsigned long long on the micky OS) - uint64_t
    is less typing.


    Why not plain 'unsigned' ?


    Did you not read the paragraph you are responding to?

    I missed the part about "using the same type". Sorry.
    Now, when I read it ... no, I don't think that it is logical.




    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tim Rentsch@3:633/10 to All on Sat Aug 15 16:16:38 2026
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value [...] */ >>>>> uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum value [...] */ >>>>> uint32_t cimin : 8; /**< R/W/H - COMINIT minimum value [...] */ >>>>> uint32_t cimax : 8; /**< R/W/H - COMINIT maximum value [...] */ >>>>> #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields type.
    I would just use unsigned, which is just as sure to work as intended,
    isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification. Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u. My question is only about the type used for the bitfields. Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    I haven't canvassed all the available platforms, and don't have
    any desire so to do. In my opinion, using the same type for the
    bitfield members as was used for the corresponding union
    element is simply logical. If we declare the integer part
    of the union as uint64_t, we use the same time for the
    bitfields (and yes, we could have used unsigned long
    (or unsigned long long on the micky OS) - uint64_t
    is less typing.

    To me it seems more logical to use the smallest basic type that
    suffices for the width of the associated bit-field, assuming
    the compiler allows it, or 'unsigned' for compilers that don't
    provide those extensions.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tim Rentsch@3:633/10 to All on Sat Aug 15 17:31:36 2026
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value [...] */ >>>>> uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum value [...] */ >>>>> uint32_t cimin : 8; /**< R/W/H - COMINIT minimum value [...] */ >>>>> uint32_t cimax : 8; /**< R/W/H - COMINIT maximum value [...] */ >>>>> #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields type.
    I would just use unsigned, which is just as sure to work as intended,
    isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification. Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u. My question is only about the type used for the bitfields. Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    I haven't canvassed all the available platforms, and don't have
    any desire so to do. In my opinion, using the same type for the
    bitfield members as was used for the corresponding union
    element is simply logical. If we declare the integer part
    of the union as uint64_t, we use the same time for the
    bitfields (and yes, we could have used unsigned long
    (or unsigned long long on the micky OS) - uint64_t
    is less typing.

    Out of curiosity I put together a short program to explore how
    bit-field types are understood by the compiler. Here is the
    program:

    #include <stdio.h>
    #include <stdint.h>

    typedef struct {
    _Bool ub : 1;
    unsigned char uc : 8;
    unsigned short us :16;
    unsigned int ui :32;
    unsigned long ul :64;
    unsigned long long ull :64;

    uint8_t u1 : 1;
    uint8_t u8 : 8;
    uint16_t u16 :16;
    uint32_t u32 :32;
    uint64_t u64 :64;

    uint64_t x1 : 1;
    uint64_t x8 : 8;
    uint64_t x16 :16;
    uint64_t x32 :32;
    uint64_t x64 :64;
    } Bitfields;

    #define whatkind(e) ( \
    _Generic( e, \
    _Bool : "_Bool", \
    unsigned char : "unsigned char", \
    unsigned short : "unsigned short", \
    unsigned int : "unsigned int", \
    unsigned long : "unsigned long", \
    unsigned long long : "unsigned long long", \
    default : "<something else>" \
    ) \
    )

    int
    main(){
    Bitfields bf;
    printf( " whatkind( bf.ub ) is %s\n", whatkind( bf.ub ) );
    printf( " whatkind( bf.uc ) is %s\n", whatkind( bf.uc ) );
    printf( " whatkind( bf.us ) is %s\n", whatkind( bf.us ) );
    printf( " whatkind( bf.ui ) is %s\n", whatkind( bf.ui ) );
    printf( " whatkind( bf.ul ) is %s\n", whatkind( bf.ul ) );
    printf( " whatkind( bf.ull ) is %s\n", whatkind( bf.ull ) );
    printf( "\n" );

    printf( " whatkind( bf.u1 ) is %s\n", whatkind( bf.u1 ) );
    printf( " whatkind( bf.u8 ) is %s\n", whatkind( bf.u8 ) );
    printf( " whatkind( bf.u16 ) is %s\n", whatkind( bf.u16 ) );
    printf( " whatkind( bf.u32 ) is %s\n", whatkind( bf.u32 ) );
    printf( " whatkind( bf.u64 ) is %s\n", whatkind( bf.u64 ) );
    printf( "\n" );

    printf( " whatkind( bf.x1 ) is %s\n", whatkind( bf.x1 ) );
    printf( " whatkind( bf.x8 ) is %s\n", whatkind( bf.x8 ) );
    printf( " whatkind( bf.x16 ) is %s\n", whatkind( bf.x16 ) );
    printf( " whatkind( bf.x32 ) is %s\n", whatkind( bf.x32 ) );
    printf( " whatkind( bf.x64 ) is %s\n", whatkind( bf.x64 ) );
    }

    and the output (using gcc)

    whatkind( bf.ub ) is _Bool
    whatkind( bf.uc ) is unsigned char
    whatkind( bf.us ) is unsigned short
    whatkind( bf.ui ) is unsigned int
    whatkind( bf.ul ) is unsigned long
    whatkind( bf.ull ) is unsigned long long

    whatkind( bf.u1 ) is <something else>
    whatkind( bf.u8 ) is unsigned char
    whatkind( bf.u16 ) is unsigned short
    whatkind( bf.u32 ) is unsigned int
    whatkind( bf.u64 ) is unsigned long

    whatkind( bf.x1 ) is <something else>
    whatkind( bf.x8 ) is unsigned char
    whatkind( bf.x16 ) is unsigned short
    whatkind( bf.x32 ) is unsigned int
    whatkind( bf.x64 ) is unsigned long

    and the output (using clang)

    whatkind( bf.ub ) is _Bool
    whatkind( bf.uc ) is unsigned char
    whatkind( bf.us ) is unsigned short
    whatkind( bf.ui ) is unsigned int
    whatkind( bf.ul ) is unsigned long
    whatkind( bf.ull ) is unsigned long long

    whatkind( bf.u1 ) is unsigned char
    whatkind( bf.u8 ) is unsigned char
    whatkind( bf.u16 ) is unsigned short
    whatkind( bf.u32 ) is unsigned int
    whatkind( bf.u64 ) is unsigned long

    whatkind( bf.x1 ) is unsigned long
    whatkind( bf.x8 ) is unsigned long
    whatkind( bf.x16 ) is unsigned long
    whatkind( bf.x32 ) is unsigned long
    whatkind( bf.x64 ) is unsigned long

    which serves to reinforce my view that bit-field types should be
    chosen from the basic types, and should be the narrowest type that
    covers the width of the corresponding bit-field member (with
    possible adjustment for widths that match two types, as for example
    unsigned long and unsigned long long).

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Sun Aug 16 13:52:13 2026
    On 15/08/2026 8:18 AM, bart wrote:
    On 14/08/2026 22:02, Johann 'Myrkraverk' Oskarsson wrote:
    On 15/08/2026 3:51 AM, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah.ÿ This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    ÿÿ uint32_t u;
    ÿÿ struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    ÿÿÿÿ uint32_t weÿÿÿÿ :ÿ 1; /**< R/W/H - Write enable. */
    ÿÿÿÿ uint32_t cwminÿ :ÿ 7; /**< R/W/H - COMWAKE minimum value
    [...] */
    ÿÿÿÿ uint32_t cwmaxÿ :ÿ 8; /**< R/W/H - COMWAKE maximum value
    [...] */
    ÿÿÿÿ uint32_t ciminÿ :ÿ 8; /**< R/W/H - COMINIT minimum value
    [...] */
    ÿÿÿÿ uint32_t cimaxÿ :ÿ 8; /**< R/W/H - COMINIT maximum value
    [...] */
    #else
    ÿÿÿÿ uint32_t cimaxÿ :ÿ 8;
    ÿÿÿÿ uint32_t ciminÿ :ÿ 8;
    ÿÿÿÿ uint32_t cwmaxÿ :ÿ 8;
    ÿÿÿÿ uint32_t cwminÿ :ÿ 7;
    ÿÿÿÿ uint32_t weÿÿÿÿ :ÿ 1;
    #endif
    ÿÿ } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields type. >>>>> I would just use unsigned, which is just as sure to work as intended, >>>>> isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification.ÿ Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u.ÿ My question is only about the type used for the bitfields.ÿ Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    Yes, people still code real mode DOS for fun and amusement.ÿ Not to
    mention boot strapping code for /real operating systems/, for some value
    of /real/.

    On 6502, int is 16bit, I believe, for reasons.ÿ And I also believe it
    makes total sense to keep int 16bit on a 68000.


    WTF are you on about? If you're an actual human then I suggest getting
    some help. If not then where the hell does all this bilge come from?


    Hey bart! You fucking piece of shit asshole. Tim asked a question. I answered it. There is a difference between 'unsigned' and 'uint32_t' on
    DOS, you fucking piece of shit know-nothing slob burger.

    Now, if Tim decides real mode DOS is not a target for his own question,
    then he should be answering with a polite followup, or spew his own
    hatred, and not you, you miserable psychopath!


    There are other hardware registers in our implementation of the SATA
    controller that are defined as 64-bit registers, for those we use
    uint64_t (rather than relying on 'unsigned long' for 64-bit linux
    or 'unsigned long long' for 32-bit OS - and this code was designed
    to be compiled for both 32-bit and 64-bit targets originally).

    Sure, for the non-bitfield member.ÿ My question is only about
    (unsigned) bitfields all of width 8 or less.

    I'm ignorant of the prior discussion, so I'll stop now; happy retro-
    coding!

    'Happy' - OK, CMT has finally convinced me!

    Happy living in alt.fantasy, you fucking piece of shit!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Sun Aug 16 14:38:39 2026
    Michael S <already5chosen@yahoo.com> writes:
    On Sat, 15 Aug 2026 19:39:54 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Michael S <already5chosen@yahoo.com> writes:
    On Fri, 14 Aug 2026 21:42:38 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one
    of the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value
    [...] */ uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum
    value [...] */ uint32_t cimin : 8; /**< R/W/H - COMINIT
    minimum value [...] */ uint32_t cimax : 8; /**< R/W/H -
    COMINIT maximum value [...] */ #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields
    type. I would just use unsigned, which is just as sure to work
    as intended, isn't it?

    The SATA hardware register is defined as a 32-bit register in
    the SATA specification. Therefore we explicitly declare it as
    such.

    I understand the motivation for using uint32_t for the union
    member u. My question is only about the type used for the
    bitfields. Do you know of any platform, or even suspect that
    there might be a platform, where using 'unsigned' rather than
    'uint32_t' for the type of the bitfields makes any difference at
    all?

    I haven't canvassed all the available platforms, and don't have
    any desire so to do. In my opinion, using the same type for the
    bitfield members as was used for the corresponding union
    element is simply logical. If we declare the integer part
    of the union as uint64_t, we use the same time for the
    bitfields (and yes, we could have used unsigned long
    (or unsigned long long on the micky OS) - uint64_t
    is less typing.


    Why not plain 'unsigned' ?


    Did you not read the paragraph you are responding to?

    I missed the part about "using the same type". Sorry.
    Now, when I read it ... no, I don't think that it is logical.


    Using unsigned for the bitfields wouldn't work properly
    if the modeled register is 64 bits and any of the fields
    are more than 32 bits in size.

    I've never liked using unadorned 'unsigned' in C.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Sun Aug 16 16:11:44 2026
    scott@slp53.sl.home (Scott Lurndal) writes:
    Michael S <already5chosen@yahoo.com> writes:
    On Sat, 15 Aug 2026 19:39:54 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:
    Michael S <already5chosen@yahoo.com> writes:
    [...]
    Why not plain 'unsigned' ?

    Did you not read the paragraph you are responding to?

    I missed the part about "using the same type". Sorry.
    Now, when I read it ... no, I don't think that it is logical.

    Using unsigned for the bitfields wouldn't work properly
    if the modeled register is 64 bits and any of the fields
    are more than 32 bits in size.

    If you need a bitfield wider than the width of int, of course you
    have to use some implementation-defined type. There's no way to
    do that portably unless you have C23. (C23 requires support for
    bit-fields of bit-precise integer types, so up to at least 64 bits,
    but still doesn't require support for bit-fields of type unsigned
    long.)

    I've never liked using unadorned 'unsigned' in C.

    I think that by "plain 'unsigned'", Michael was referring to the type,
    not necessarily to how it's named. ("unsigned", "unsigned int", and
    "int unsigned" are all the same type.)

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Dan Cross@3:633/10 to All on Tue Aug 18 20:34:54 2026
    In article <868q673rft.fsf@linuxsc.com>,
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value [...] */ >>>>>> uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum value [...] */ >>>>>> uint32_t cimin : 8; /**< R/W/H - COMINIT minimum value [...] */ >>>>>> uint32_t cimax : 8; /**< R/W/H - COMINIT maximum value [...] */ >>>>>> #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields type. >>>>> I would just use unsigned, which is just as sure to work as intended, >>>>> isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification. Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u. My question is only about the type used for the bitfields. Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    I haven't canvassed all the available platforms, and don't have
    any desire so to do. In my opinion, using the same type for the
    bitfield members as was used for the corresponding union
    element is simply logical. If we declare the integer part
    of the union as uint64_t, we use the same time for the
    bitfields (and yes, we could have used unsigned long
    (or unsigned long long on the micky OS) - uint64_t
    is less typing.

    To me it seems more logical to use the smallest basic type that
    suffices for the width of the associated bit-field, assuming
    the compiler allows it, or 'unsigned' for compilers that don't
    provide those extensions.

    You do not appear to actually write software that interfaces
    directly with hardware in the manner that Scott and I (among
    others) do.

    - Dan C.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Waldek Hebisch@3:633/10 to All on Wed Aug 19 19:57:34 2026
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    One might also define data structures for control and status
    registers using bitfield structs.

    Yeah. This kind of application (among others) I consider one of
    the motivating forces behind bitfields.

    [Some whitespace trimming done in the excerpt below.]

    e.g. for the SATA UAHC_GLB_OOBR register:

    union UAHC_GBL_OOBR {
    uint32_t u;
    struct UAHC_GBL_OOBR_s {
    #if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t we : 1; /**< R/W/H - Write enable. */
    uint32_t cwmin : 7; /**< R/W/H - COMWAKE minimum value [...] */ >>>>>> uint32_t cwmax : 8; /**< R/W/H - COMWAKE maximum value [...] */ >>>>>> uint32_t cimin : 8; /**< R/W/H - COMINIT minimum value [...] */ >>>>>> uint32_t cimax : 8; /**< R/W/H - COMINIT maximum value [...] */ >>>>>> #else
    uint32_t cimax : 8;
    uint32_t cimin : 8;
    uint32_t cwmax : 8;
    uint32_t cwmin : 7;
    uint32_t we : 1;
    #endif
    } s;
    };

    To me it seems kind of goofy to use uint32_t for the bitfields type. >>>>> I would just use unsigned, which is just as sure to work as intended, >>>>> isn't it?

    The SATA hardware register is defined as a 32-bit register in the
    SATA specification. Therefore we explicitly declare it as such.

    I understand the motivation for using uint32_t for the union member
    u. My question is only about the type used for the bitfields. Do
    you know of any platform, or even suspect that there might be a
    platform, where using 'unsigned' rather than 'uint32_t' for the type
    of the bitfields makes any difference at all?

    I haven't canvassed all the available platforms, and don't have
    any desire so to do. In my opinion, using the same type for the
    bitfield members as was used for the corresponding union
    element is simply logical. If we declare the integer part
    of the union as uint64_t, we use the same time for the
    bitfields (and yes, we could have used unsigned long
    (or unsigned long long on the micky OS) - uint64_t
    is less typing.

    To me it seems more logical to use the smallest basic type that
    suffices for the width of the associated bit-field, assuming
    the compiler allows it, or 'unsigned' for compilers that don't
    provide those extensions.

    Conider the following two structs:

    typedef struct {char a:5; char b:5; char c:5;} bf1;

    typedef struct {short a:5; short b:5; short c:5;} bf2;

    gcc allocates 3 bytes to first one and 2 bytes for the second one.
    Bitfields are frequently used to converve memory and the second
    one is better in this aspect. So it is hard the avoid notion
    of storage unit and using type to control size of storage unit.

    Of course, if you can not count on compiler behaving in specific
    way, abd you can not tolerate different behaviour, then it is better
    to use access if given needed size and masks and shifts to access
    the bits.

    --
    Waldek Hebisch

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tim Rentsch@3:633/10 to All on Sun Aug 23 07:56:58 2026
    scott@slp53.sl.home (Scott Lurndal) writes:

    I've never liked using unadorned 'unsigned' in C.

    Can you say why that is? Do you also, for example, never
    use 'long' but always use 'long int'?

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Sun Aug 23 17:37:14 2026
    On 23/08/2026 16:56, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    I've never liked using unadorned 'unsigned' in C.

    Can you say why that is? Do you also, for example, never
    use 'long' but always use 'long int'?

    For me, personally, it simply sounds like poor grammar to use a
    standalone adjective instead of a noun. If I see "unsigned" or "long",
    I am thinking "unsigned /what/ ?" "long /what/ ?". Of course I know
    what these mean when I read them in C code, but it just looks and feels
    ugly and incomplete.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Sun Aug 23 16:08:08 2026
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:

    I've never liked using unadorned 'unsigned' in C.

    Can you say why that is?

    Because I consider it a qualifier rather than a type,
    regardless of how the language defines it. A personal
    quirk, if you will.

    Do you also, for example, never
    use 'long' but always use 'long int'?

    Actually, 99.9% of the time, I use <stdint.h> types rather
    than the core C types. I also consider 'long' a qualifier,
    so yes, I would use 'long int' (or long long) if necessary.

    Note that I exclusively program at very low levels for
    operating system code, hypervisor code and various
    simulators where matching the hardware characteristics
    is key.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Sun Aug 23 16:09:01 2026
    David Brown <david.brown@hesbynett.no> writes:
    On 23/08/2026 16:56, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    I've never liked using unadorned 'unsigned' in C.

    Can you say why that is? Do you also, for example, never
    use 'long' but always use 'long int'?

    For me, personally, it simply sounds like poor grammar to use a
    standalone adjective instead of a noun. If I see "unsigned" or "long",
    I am thinking "unsigned /what/ ?" "long /what/ ?". Of course I know
    what these mean when I read them in C code, but it just looks and feels
    ugly and incomplete.


    Agreed.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tim Rentsch@3:633/10 to All on Sun Aug 23 10:54:11 2026
    antispam@fricas.org (Waldek Hebisch) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    [on deciding which type to use for a bit-field member]

    To me it seems more logical to use the smallest basic type that
    suffices for the width of the associated bit-field, assuming
    the compiler allows it, or 'unsigned' for compilers that don't
    provide those extensions.

    Conider the following two structs:

    typedef struct {char a:5; char b:5; char c:5;} bf1;

    typedef struct {short a:5; short b:5; short c:5;} bf2;

    gcc allocates 3 bytes to first one and 2 bytes for the second one.

    That's interesting; thank you for the research. I wouldn't
    expect code to use char for a bit-field type but presumably
    unsigned char or signed char would give the same result.

    Bitfields are frequently used to converve memory and the second
    one is better in this aspect. So it is hard the avoid notion
    of storage unit and using type to control size of storage unit.

    In the early days of C conserving space may have been a common
    consideration. These days I expect it hardly ever is, except
    perhaps in the case of lots of _Bool bit-fields.

    Furthermore there are advantages to using a type where the
    members occupy separate bytes rather than being packed into a
    single 16-bit object. The generated code may be better. Also
    using a single byte for each member reduces the change of
    undefined behavior when accessing these bit-fields.

    Of course, if you can not count on compiler behaving in specific
    way, abd you can not tolerate different behaviour, then it is better
    to use access if given needed size and masks and shifts to access
    the bits.

    I hope it goes without saying that whenever it is necessary to
    conform to an externally imposed layout, and bit-fields are used
    to effect that, that the layout produced by the compiler(s)
    should be checked against the external specification, and that
    whatever type-selection heuristics are used should be adjusted to
    ensure the needed conformance does in fact occur. Using masks
    and shifts -- and probably macros -- can provide a more reliable
    alternative in some cases; but that approach also carries its
    own set of downsides, which need to be weighed against other
    approaches.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Waldek Hebisch@3:633/10 to All on Sun Aug 23 21:22:06 2026
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
    antispam@fricas.org (Waldek Hebisch) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    [on deciding which type to use for a bit-field member]

    To me it seems more logical to use the smallest basic type that
    suffices for the width of the associated bit-field, assuming
    the compiler allows it, or 'unsigned' for compilers that don't
    provide those extensions.

    Conider the following two structs:

    typedef struct {char a:5; char b:5; char c:5;} bf1;

    typedef struct {short a:5; short b:5; short c:5;} bf2;

    gcc allocates 3 bytes to first one and 2 bytes for the second one.

    That's interesting; thank you for the research. I wouldn't
    expect code to use char for a bit-field type but presumably
    unsigned char or signed char would give the same result.

    Yes, the same result.

    Bitfields are frequently used to converve memory and the second
    one is better in this aspect. So it is hard the avoid notion
    of storage unit and using type to control size of storage unit.

    In the early days of C conserving space may have been a common
    consideration. These days I expect it hardly ever is, except
    perhaps in the case of lots of _Bool bit-fields.

    Maybe people care less on total memory use, but is rather common
    to care about speed. And experience shows that small, tightly
    packed data structures frequently lead to faster code.

    Furthermore there are advantages to using a type where the
    members occupy separate bytes rather than being packed into a
    single 16-bit object. The generated code may be better. Also
    using a single byte for each member reduces the change of
    undefined behavior when accessing these bit-fields.

    But why use bitfields in such case? AFAICS when there is a single
    bitfield in a byte gcc still is masking and extracting the
    field. And write operation produces full read-modify-write
    seqence. So using appropriate variant of char would reduce
    number of instructions.

    Concerning generated code, on reasonably big machines I would
    expect 32-bit access to be quite efficient and on 64-bit machines
    64-bit access is likely to be quite efficient. 8-bit versus
    16-bit access is going to be quite machine specific.

    --
    Waldek Hebisch

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Sun Aug 23 19:42:30 2026
    On 8/23/2026 8:37 AM, David Brown wrote:
    On 23/08/2026 16:56, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    I've never liked using unadorned 'unsigned' in C.

    Can you say why that is?ÿ Do you also, for example, never
    use 'long' but always use 'long int'?

    For me, personally, it simply sounds like poor grammar to use a
    standalone adjective instead of a noun.ÿ If I see "unsigned" or "long",
    I am thinking "unsigned /what/ ?"ÿ "long /what/ ?".ÿ Of course I know
    what these mean when I read them in C code, but it just looks and feels
    ugly and incomplete.


    long is fine with me. well, signed long? ;^)

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Mon Aug 24 10:27:34 2026
    On 24/08/2026 04:42, Chris M. Thomasson wrote:
    On 8/23/2026 8:37 AM, David Brown wrote:
    On 23/08/2026 16:56, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    I've never liked using unadorned 'unsigned' in C.

    Can you say why that is?ÿ Do you also, for example, never
    use 'long' but always use 'long int'?

    For me, personally, it simply sounds like poor grammar to use a
    standalone adjective instead of a noun.ÿ If I see "unsigned" or
    "long", I am thinking "unsigned /what/ ?"ÿ "long /what/ ?".ÿ Of course
    I know what these mean when I read them in C code, but it just looks
    and feels ugly and incomplete.


    long is fine with me. well, signed long? ;^)

    I'm with Scott on this topic - it's a personal dislike, and not
    something that I expect everyone else to share. It's like poor or inconsistent use of spaces in code, which I find grating.

    And like Scott, I use mainly <stdint.h> types unless I need
    compatibility or consistency with existing code. (The exception is that
    "int" is the common C type for "a number".) I find it hard to
    understand why someone would ever want to use a type that is mostly like
    a number of unspecified range, but possibly a bit bigger, at least 32
    bits but maybe more, and different on different systems. If I want to
    hold a signed 32-bit value, I use "int32_t". If I want to hold a signed 32-bit value and I know the code is time-critical on bigger processors,
    I use "int_fast32_t".

    But that's for the programming /I/ do - other people can have different opinions, preferences and choices.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Mon Aug 24 10:37:51 2026
    On 23/08/2026 23:22, Waldek Hebisch wrote:
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
    antispam@fricas.org (Waldek Hebisch) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    [on deciding which type to use for a bit-field member]

    To me it seems more logical to use the smallest basic type that
    suffices for the width of the associated bit-field, assuming
    the compiler allows it, or 'unsigned' for compilers that don't
    provide those extensions.

    Conider the following two structs:

    typedef struct {char a:5; char b:5; char c:5;} bf1;

    typedef struct {short a:5; short b:5; short c:5;} bf2;

    gcc allocates 3 bytes to first one and 2 bytes for the second one.

    That's interesting; thank you for the research. I wouldn't
    expect code to use char for a bit-field type but presumably
    unsigned char or signed char would give the same result.

    Yes, the same result.

    Bitfields are frequently used to converve memory and the second
    one is better in this aspect. So it is hard the avoid notion
    of storage unit and using type to control size of storage unit.

    In the early days of C conserving space may have been a common
    consideration. These days I expect it hardly ever is, except
    perhaps in the case of lots of _Bool bit-fields.

    Maybe people care less on total memory use, but is rather common
    to care about speed. And experience shows that small, tightly
    packed data structures frequently lead to faster code.

    As the saying goes, over a certain size all programming is an exercise
    in caching. On a PC where fetching data from main memory takes several hundred clock cycles, you can do a /lot/ of packing into and out of
    bit-fields if the structure gives you more cache-friendly struct sizes
    or higher hit/miss ratios.


    Furthermore there are advantages to using a type where the
    members occupy separate bytes rather than being packed into a
    single 16-bit object. The generated code may be better. Also
    using a single byte for each member reduces the change of
    undefined behavior when accessing these bit-fields.

    But why use bitfields in such case? AFAICS when there is a single
    bitfield in a byte gcc still is masking and extracting the
    field. And write operation produces full read-modify-write
    seqence. So using appropriate variant of char would reduce
    number of instructions.

    I /think/ Tim meant using individual bytes rather than bit-fields - so
    "struct { bool a; uint8_t b; };" rather than bit-fields.

    But I don't know what he meant by "reduces the change of undefined
    behavior when accessing these bit-fields". Maybe "chance of UB" ? The
    only thing I can think of is if different threads tried to access
    different bit-fields within the same storage unit without proper synchronisation - that could certainly lead to UB. With separate bytes,
    the behaviour is likely to be defined - just really slow due to cache conflicts.


    Concerning generated code, on reasonably big machines I would
    expect 32-bit access to be quite efficient and on 64-bit machines
    64-bit access is likely to be quite efficient. 8-bit versus
    16-bit access is going to be quite machine specific.



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Janis Papanagnou@3:633/10 to All on Wed Aug 26 03:38:05 2026
    On 2026-08-23 18:08, Scott Lurndal wrote:
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:

    I've never liked using unadorned 'unsigned' in C.

    Can you say why that is?

    Because I consider it a qualifier rather than a type,
    regardless of how the language defines it. A personal
    quirk, if you will.

    I think "C" borrowed that LONG/SHORT from Algol 68, but
    unlike Algol 68 where these are modifiers "C" went in a
    different direction. Their original "taste" as modifiers
    still persist even in "C", so I understand the preference.
    (Incidentally, our C/C++ coding standards back in the 90's
    suggested (or even demanded?) to use full qualification.)

    Janis


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tim Rentsch@3:633/10 to All on Thu Aug 27 13:05:17 2026
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    I've never liked using unadorned 'unsigned' in C.

    Can you say why that is?

    Because I consider it a qualifier rather than a type,
    regardless of how the language defines it. A personal
    quirk, if you will.

    Do you also, for example, never
    use 'long' but always use 'long int'?

    {sentence moved to later} I also consider 'long' a qualifier,
    so yes, I would use 'long int' (or long long) if necessary.

    I think I understand. If another developer had a different
    personal preference, would you consider that equally valid, even
    if it didn't affect your own style choices?

    BTW I assume you mean 'long long int' for the phrase in
    parentheses.

    {moved here} Actually, 99.9% of the time, I use <stdint.h>
    types rather than the core C types.

    I presume that in almost all cases these types are the fixed
    width types. Do you have any occasion to use either the fast
    types or least-width types from <stdint.h>?

    Note that I exclusively program at very low levels for
    operating system code, hypervisor code and various
    simulators where matching the hardware characteristics
    is key.

    Am I right in assuming that these factors are orthogonal to the
    question of what names are used for types outside of the types
    defined in <stdint.h>?

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tim Rentsch@3:633/10 to All on Sun Aug 30 10:44:57 2026
    antispam@fricas.org (Waldek Hebisch) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    antispam@fricas.org (Waldek Hebisch) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    [on deciding which type to use for a bit-field member]

    To me it seems more logical to use the smallest basic type that
    suffices for the width of the associated bit-field, assuming
    the compiler allows it, or 'unsigned' for compilers that don't
    provide those extensions.

    Conider the following two structs:

    typedef struct {char a:5; char b:5; char c:5;} bf1;

    typedef struct {short a:5; short b:5; short c:5;} bf2;

    gcc allocates 3 bytes to first one and 2 bytes for the second one.

    That's interesting; thank you for the research. I wouldn't
    expect code to use char for a bit-field type but presumably
    unsigned char or signed char would give the same result.

    Yes, the same result.

    Bitfields are frequently used to converve memory and the second
    one is better in this aspect. So it is hard the avoid notion
    of storage unit and using type to control size of storage unit.

    In the early days of C conserving space may have been a common
    consideration. These days I expect it hardly ever is, except
    perhaps in the case of lots of _Bool bit-fields.

    Maybe people care less on total memory use, but is rather common
    to care about speed. And experience shows that small, tightly
    packed data structures frequently lead to faster code.

    Furthermore there are advantages to using a type where the
    members occupy separate bytes rather than being packed into a
    single 16-bit object. The generated code may be better. Also
    using a single byte for each member reduces the change of
    undefined behavior when accessing these bit-fields.

    But why use bitfields in such case?

    To limit the range of values that can be stored.

    AFAICS when there is a single
    bitfield in a byte gcc still is masking and extracting the
    field. And write operation produces full read-modify-write
    seqence. So using appropriate variant of char would reduce
    number of instructions.

    Allowing the full range of a basic integer type, rather than
    using a bit-field, would give different semantics.

    Concerning generated code, on reasonably big machines I would
    expect 32-bit access to be quite efficient and on 64-bit machines
    64-bit access is likely to be quite efficient. 8-bit versus
    16-bit access is going to be quite machine specific.

    I don't see anything in what you wrote that contradicts what
    I wrote.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Kragen Javier Sitaker@3:633/10 to All on Wed Sep 2 00:24:29 2026
    Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> writes:
    Hey bart! You fucking piece of shit asshole.

    My.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Thu Sep 3 00:55:18 2026
    On Sun, 23 Aug 2026 21:22:06 -0000 (UTC), Waldek Hebisch wrote:

    AFAICS when there is a single bitfield in a byte gcc still is
    masking and extracting the field.

    Some instruction sets have, or used to have, instructions for inserting/extracting variable-length bitfields. Not sure if these are
    faster than shift/mask, though.

    And unlike shift/mask, they are endian-dependent.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Thu Sep 3 09:18:17 2026
    On 03/09/2026 02:55, Lawrence D?Oliveiro wrote:
    On Sun, 23 Aug 2026 21:22:06 -0000 (UTC), Waldek Hebisch wrote:

    AFAICS when there is a single bitfield in a byte gcc still is
    masking and extracting the field.

    Some instruction sets have, or used to have, instructions for inserting/extracting variable-length bitfields. Not sure if these are
    faster than shift/mask, though.

    And unlike shift/mask, they are endian-dependent.

    Bit-field extraction and insertion instructions will obviously be faster
    than shifting and masking - a processor ISA is not going to have them in
    the instruction set unless they are. Generally these types of
    instructions are single-cycle, while a shift-and-mask set will take
    several instructions and at least as many cycles.

    And no, they are not endian-dependent in any way that is meaningful for
    C programming. You write the C code, and the compiler generates mask-and-shift or bit-field instructions depending on which the target supports, with the same semantics.

    Of course, explicit manual shift-and-mask expressions operate on values,
    which are independent of target endianness, while all the underlying representation of all C bit-field declarations and operations are
    dependent on the bit-ordering picked by the compiler (which may or may
    not depend on the byte ordering of the target processor).

    #include <stdint.h>

    typedef struct S {
    uint32_t a : 12;
    uint32_t b : 14;
    uint32_t c : 6;
    } S;

    uint32_t get_b(S s)
    {
    return s.b;
    }

    S set_b(S s, uint32_t x)
    {
    s.b = x;
    return s;
    }

    Compiling with 32-bit arm gcc 16 with "-O2 -march=armv7" gives :

    get_b:
    ubfx r0, r0, #12, #14
    bx lr
    set_b:
    bfi r0, r1, #12, #14
    bx lr

    Compiling with "-O2 -march=armv6", without bit-field instructions :

    get_b:
    ldr r3, .L3
    and r0, r3, r0, lsr #12
    bx lr
    .L3:
    .word 16383
    set_b:
    lsl r1, r1, #18
    bic r0, r0, #66846720
    lsr r1, r1, #18
    bic r0, r0, #258048
    orr r0, r0, r1, lsl #12
    bx lr

    Clearly the bit-field instructions are significantly more efficient in
    this example. I do not expect other processors to be different.




    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Waldek Hebisch@3:633/10 to All on Thu Sep 3 19:36:09 2026
    Lawrence D?Oliveiro <ldo@nz.invalid> wrote:
    On Sun, 23 Aug 2026 21:22:06 -0000 (UTC), Waldek Hebisch wrote:

    AFAICS when there is a single bitfield in a byte gcc still is
    masking and extracting the field.

    Some instruction sets have, or used to have, instructions for inserting/extracting variable-length bitfields. Not sure if these are
    faster than shift/mask, though.

    AFAIK no processor that I use have support for variable-length
    (or variable position) bitfields. But C bitfields have length
    and position known at compile time and what ARM has is enough
    to extract or set a bitfield in a register using single
    instruction.

    --
    Waldek Hebisch

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Thu Sep 3 23:10:11 2026
    On 03/09/2026 21:36, Waldek Hebisch wrote:
    Lawrence D?Oliveiro <ldo@nz.invalid> wrote:
    On Sun, 23 Aug 2026 21:22:06 -0000 (UTC), Waldek Hebisch wrote:

    AFAICS when there is a single bitfield in a byte gcc still is
    masking and extracting the field.

    Some instruction sets have, or used to have, instructions for
    inserting/extracting variable-length bitfields. Not sure if these are
    faster than shift/mask, though.

    AFAIK no processor that I use have support for variable-length
    (or variable position) bitfields. But C bitfields have length
    and position known at compile time and what ARM has is enough
    to extract or set a bitfield in a register using single
    instruction.


    Was Lawrence talking about bit-fields whose length is not known at
    compile time? I have never come across such a thing - certainly C has
    no direct support for it. I suppose you could have a bit array and
    views or slices of part of that, but you would presumably have to deal
    with slices that do not fit into any containing element. It would be
    quite inefficient to deal with such an object, but if it is big enough,
    the cache space savings might make it a suitable choice of structure.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Thu Sep 3 15:15:58 2026
    antispam@fricas.org (Waldek Hebisch) writes:
    Lawrence D?Oliveiro <ldo@nz.invalid> wrote:
    On Sun, 23 Aug 2026 21:22:06 -0000 (UTC), Waldek Hebisch wrote:

    AFAICS when there is a single bitfield in a byte gcc still is
    masking and extracting the field.

    Some instruction sets have, or used to have, instructions for
    inserting/extracting variable-length bitfields. Not sure if these are
    faster than shift/mask, though.

    AFAIK no processor that I use have support for variable-length
    (or variable position) bitfields. But C bitfields have length
    and position known at compile time and what ARM has is enough
    to extract or set a bitfield in a register using single
    instruction.

    FWIW, the 68020/68030/68040 BFINS (bit field insert) instruction
    allows the width and offset to be specified either as immediate
    operands or as the value stored in a register. I can't think of
    a use for this in C unless the compiler is being *really* clever.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Waldek Hebisch@3:633/10 to All on Fri Sep 4 00:54:06 2026
    David Brown <david.brown@hesbynett.no> wrote:
    On 03/09/2026 21:36, Waldek Hebisch wrote:
    Lawrence D?Oliveiro <ldo@nz.invalid> wrote:
    On Sun, 23 Aug 2026 21:22:06 -0000 (UTC), Waldek Hebisch wrote:

    AFAICS when there is a single bitfield in a byte gcc still is
    masking and extracting the field.

    Some instruction sets have, or used to have, instructions for
    inserting/extracting variable-length bitfields. Not sure if these are
    faster than shift/mask, though.

    AFAIK no processor that I use have support for variable-length
    (or variable position) bitfields. But C bitfields have length
    and position known at compile time and what ARM has is enough
    to extract or set a bitfield in a register using single
    instruction.


    Was Lawrence talking about bit-fields whose length is not known at
    compile time? I have never come across such a thing - certainly C has
    no direct support for it. I suppose you could have a bit array and
    views or slices of part of that, but you would presumably have to deal
    with slices that do not fit into any containing element. It would be
    quite inefficient to deal with such an object, but if it is big enough,
    the cache space savings might make it a suitable choice of structure.

    Lawrence wrote "variable-length bitfields". In context of compiled
    languages like C I would not use word "variable" to describe something
    that is compile time constant. In context of ARM current instruction
    contains inside two numbers. Taking those two numbers from register
    should have small impact on execution time of those instruction.
    In case of things that fit into two words, but may span word
    boundary ARM64 has instruction that extract word sized slice from
    two words. If also this instruction allowed register specification,
    then two istructions could extract needed variable slice. If you
    want to extract things from memory, then you also need appropriate
    conditional load (doing second load unconditionally may segfault).

    Without proper support in instruction set such things can be quite
    inefficient, so there is some motivation to provide them. OTOH
    to use them C compiler would have to recognize appropriate idioms
    or provide them as an extention.

    --
    Waldek Hebisch

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)