Earlier quoted context omitted.
Uh, that's standard C89. You know, the bit fields? Except for the "false" keyword, that's from stdbool.h and you need C99 for that to reliably exist.
The only real problem with C (and C++) bitfields is that the standard doesn’t say anything about how they’re laid out in memory, which unfortunately makes them mostly useless unless you either don’t care about layout or you’re targeting one specific compiler and that compiler documents its choices and doesn’t break them in a few years. Sign-extension of 1-bit fields also messes people up all the time, but that’s “jus…
Packed structs in Zig make bit/flag sets trivial
81–90 of 147 posts
Re: Packed structs in Zig make bit/flag sets trivial
#82Earlier quoted context omitted.
Wow... I thought I had seen a lot of strange C++ code but I have _never_ seen packed structs using this syntax: struct X { type alias : numeric_value = false; ... } I love the power of C++ but there is _so much_ to the language. I'm sure there would also be some template meta programming solution even if this syntax was available.
It's probably tough to find a metaprogramming solution to this, for two reasons: 1. Addressing happens at the byte level, not the bit level, so a type can't begin on any bit. You'd have to do your own addressing, such as in std::bitset. 2. For now, there's no reflection in the language, so you can't really assign names to members in a general way (hello, preprocessor). A solution might be to index by type; something…
Re: Packed structs in Zig make bit/flag sets trivial
#83Earlier quoted context omitted.
The in-memory representation of bit fields is implementation-defined. Therefore, if you're calling into an external API that takes a uint32_t like in the example without an explicit remapping, you may or may not like the results. In practice, everything you're likely to come across will be little endian nowadays, and the ABI you're using will most likely order your struct from top to bottom in memory, so they will lo…
I've dealt with oddities talking between big endian powerpc using these. Its been a few years but the difference wasn't just the endianess I think? Still, dealing with the mapping was way easier than masking for large structs. Is big endian really dead now?
Re: Packed structs in Zig make bit/flag sets trivial
#84Earlier quoted context omitted.
Red is the least significant bit, because offsets start at bit #0. Endianness is not a concern because you have to specify the underlying integer type, and bit endianness is not a thing, so it's just the native endianness (if you, e.g., need a network format with specific endianness and a 32-bit bitfield, you can instead use 4 consecutive 8-bit bitfields laid out in a consistent way). Unspecified bits are ignored; th…
> Red is the least significant bit, because offsets start at bit #0. So red is the LSB because you decided it was the LSB. That is not a by-definition thing. > Endianness is not a concern because you have to specify the underlying integer type, and bit endianness is not a thing That’s not actually true. There are formats which process bytes LSB to MSB, and formats which process them MSB to LSB. E.g. git’s offset-enco…
By 'field' I meant the contained sub-fields
Re: Packed structs in Zig make bit/flag sets trivial
#85Earlier quoted context omitted.
I’ve definitely desired an operator that combines these before. I’ve settled on &== as the best syntax in C-style languages, with a &== b being equivalent to a & b == b (but with a single evaluation of b). if (mask &== WGPUColorWriteMask_Alpha|WGPUColorWriteMask_Blue) { … } I find only two very minor problems with it: firstly, that it’s not commutative (that is, a &== b is not equivalent to b &== a ). Secondly, that…
> I find only two very minor problems with it: firstly, that it’s not commutative Why is that a problem? That is, if a has additional bits set compared to b, then ((a & b) == b) != ((b & a) == a), no?
For equality comparisons, there are two opposing conventions: actual == expected (the more popular, in my experience), and expected == actual (by no means rare). Having &== and |== be order-sensitive (though there’s absolutely no question in my mind about what the ordering should be) is mildly unfortunate.
It’s very minor.
Re: Packed structs in Zig make bit/flag sets trivial
#86Earlier quoted context omitted.
Here is a sample of how you do this in C++ https://godbolt.org/z/W3bMcqM5P
I thought you were not able to initialize bitfield members like that in struct. Am I misremembering, was that something else or is it compiler/c++ release dependent?
Re: Packed structs in Zig make bit/flag sets trivial
#87Earlier quoted context omitted.
This has been possible since C89. See 3.5.2.1 of the C89 rationale [0]. It is architecture/compiler dependent though. This is explicitly acknowledged in the rationale document: “Since some existing implementations, in the interest of enhanced access time, leave internal holes larger than absolutely necessary, it is not clear that a portable deterministic method can be given for traversing a structure field by field.”…
I think they were referring to the default member initializer, a feature added in C++11 not exclusive to bitfields. I couldn't see any reference to anything similar in what you linked (admittedly, I skimmed though). For example: struct X { int defaulted = 1; // 1 is the default member initializer };
Ah, that would make more sense. The combination of bitfield and default initializer syntax does look especially odd, since both features are rarely used IME.
>I couldn't see any reference to anything similar in what you linked
Indeed, there is no way to specify default values for a C struct at definition time.
Re: Packed structs in Zig make bit/flag sets trivial
#88Earlier quoted context omitted.
Bit fields in C are notoriously non-portable (exact physical layout depends on the compiler). Is Zig any better (apart from the fact that there is only one Zig compiler for now)?
Notoriously? I can't name any architecture/platform/compiler where bits aren't allocated consecutively in order of definition, without holes, in the same direction as system endianness...
MSVC does things simply, gcc does not
Re: Packed structs in Zig make bit/flag sets trivial
#89This is a nice syntax, but the functionality seems essentially the same as bit fields in C. Does this provide anything additional?
D just went ahead and implemented bit fields. They work, and it's hard to find any way to improve on them.
Similarly bitfields mean you end up with "ints" that are actually 3 bits wide and so on.
Re: Packed structs in Zig make bit/flag sets trivial
#90Earlier quoted context omitted.
> It is not possible to specify bitfields in a way that makes sense, is consistent with a bytewise view of memory, and is portable between big endian and little endian processors. I'm not sure I accept "consistency with a bytewise view of memory" as a well-defined, reasonable concept. I do expect to give a list of bit widths, and get a field that has these in consecutive order. Why would it randomly do weird things o…
> > If the fields are allocated in order, is u4 the low bits of the first byte or the high bits? > It's the low bits on LE, and the high bits on BE. You are advocating for the current rule in C. As I said, C's rule implies 8 bit fields will be in different orders in memory on machines of different endianness, which makes it very difficult to use bitfields to get exact control over memory layout in a portable manner.
Your binary isn't going to be portable. The only reason your memory layout should be is if you intend to serialize it. But if you're going that extra step, you _need_ to convert it to a platform-independent format regardless -- otherwise, not even your ints deserialize correctly.