On 11/24/2015 4:58 PM, David Brown wrote:
> [... "packed" structs and similar underhanded artifices ...]
> Also explicit packing "dummies" have the advantage that there is no
> chance of undefined, implementation-defined, unspecified or generally
> unexpected or undesired behaviour when they are accessed. (When storing
> something in a struct, padding bytes get unspecified values.) This is
> particularly important if you want to compare structs, or do something
> like calculate a checksum over them.
It's been my experience that these questions of packing and so on
nearly always arise in connection with an externally-imposed format of
some kind: You want to use a struct to represent an IP header or a
disk partition table entry or something of that sort. If that's the
situation, I've almost always found that trying to sculpt the struct
into the desired shape is inferior to just letting the struct take its
own preferred form and using a mediating buffer to translate to and
from the imposed format. Use separate "native" and "serialized" forms,
and you're quite likely to be better off than by trying to force both
forms into one object.
Not only does the separation of forms avoid all the alignment
issues discussed elsethread, but it also offers a convenient hook for
dealing with other matters. Does the external form require a specific
endianness that may or may not match your machine's? Does it use a
weird representation for negative numbers, or for floating-point
quantities? Are text strings supposed to be a count word followed
by a payload in some strange five-bit encoding? The import() and
export() functions can handle all such idiosyncracies cleanly and
quietly, so the rest of the program can deal with perfectly normal,
native-format structs with native-format numbers, zero-terminated
native-encoded strings, and so on. The translation functions are
also good places to compute and verify things like checksums, which
are usually specified in terms of the external format.
Somewhere, somebody is shrieking "Efficiency! All that copying?
Why should I un-pickle an entire object just to test the one field
that tells me whether I care about the others? Eeeek!" This shrieker
is overly fearful and insufficiently imaginative; there are plenty of
ways to attack such issues if they should prove important. (Also,
for some reason the shrieker seldom yowls about the speed penalties
of using the misaligned elements in his packed structs. Go figure.)
There are many situations where it is tempting to map an imposed
format with a struct, but resisting temptation is nearly always a
virtue, and a virtue with rewards.