bitfield confusion

Discussion in 'C Programming' started by mathog, Jul 11, 2013.

  1. mathog

    Ian Collins Guest

    Which is odd, considering both Solaris and Linux provide bit-field
    ordering macros (_BIT_FIELDS_LTOH and __BYTE_ORDER respectively) to
    support big and little endian targets.
    Ian Collins, Jul 13, 2013
    1. Advertisements

  2. mathog

    Eric Sosman Guest

    Hmmm. Okay, maybe that's a bit too telegraphic. Let's go
    into a little more detail, shall we?

    First: "Tell that to the writers of most platform's [sic]
    IP headers." Sure, I'll tell them their headers are not portable.
    I'll say the same about the platform's <setjmp.h>, <stdint.h>, and
    <float.h>: All are non-portable, in the sense that the file that
    works with one implementation need not work with the next.

    Second: "Portability has many meanings, ..." Yeah. One of
    those meanings, is "Bit-fields ain't a portable way to map an
    externally-defined format." The recipe that works on one platform
    may not work with the next.

    Third: "Some do, some don't." Or in other words, it's not
    portable. Would I use what the system provided? Yes, of course,
    just as I would use <stdio.h> and FILE*: fopen() and fprintf()
    and so on are portable; the nature of FILE is not.

    Fourth: "In all of the real wold [sic] situations I have
    seen, common sense prevails here." The lack of any definition
    of "common sense" leaves enough wiggle room for a septillion
    slippery slimy eels. Even so, "I've never seen it, ergo it
    merits no consideration" is an argument unworthy of debate.[*]

    [*] Despite the politicians, who will also say "I've never
    seen it, ergo it's a CRISIS requiring MORE FUNDS" and will
    maintain both positions simultaneously.
    Eric Sosman, Jul 13, 2013
    1. Advertisements

  3. That doesn't apply to my current (embedded) environment, where we need
    to write and support portable libraries that are used without change
    on several different architectures, under several operatings systems,
    and compiled with several different compilers.
    (I am talking about down-to-the-metal device control libraries &
    Roberto Waltman, Jul 13, 2013
  4. mathog

    Ian Collins Guest

    The apostrophe is portable to all known English dialects...
    So you would avoid setjump because it isn't portable? Obviously not. If
    at platform provides the means to use a feature, use it. This case may
    be constrained to those platforms which support networking, but you
    wouldn't be manipulating IP packets anywhere else, would you?
    True, but if it does, use it. Probably most code that works with IP
    packets isn't 100% portable C, it will contain platform specific code.
    The same applies to the other common use for bit-fields, drivers. These
    are even more platform specific.
    I'll give you that typo.
    If there is more than one compiler for a given platform, they are very
    unlikely to order bit-fields differently. Yes I haven't seen them all,
    but I have seen a lot over the past 30 years or so. If you know of a
    counterexample, I'm interested.
    Ian Collins, Jul 13, 2013
  5. mathog

    Ian Collins Guest

    Those are compelling reasons not to use bit-fields!
    Ian Collins, Jul 13, 2013
  6. mathog

    Les Cargill Guest

    I'd say fixing struct definitions which implement bit fields has
    to be easier than some of the other strategies I've seen. I'd
    be a bit (heh) nervous not hiding these in a header
    Les Cargill, Jul 13, 2013
  7. mathog

    Eric Sosman Guest

    Amend your misuse of the plural possessive apostrophe by
    consulting any standard reference for English. A few that are
    easily accessible offer:

    "two cats' toys
    three friends' letters
    the countries' laws"

    "Singers' voices
    The cousins' favorite uncle"

    "two boys' hats two women's hats
    two actresses' hats
    two children's hats
    the Changs' house
    the Joneses' golf clubs
    the Strauses' daughter
    the Sanchezes' artwork
    the Hastingses' appointment
    the Leeses' books"

    In all these examples (and others you may find for yourself),
    observe the position of the possessive apostrophe when applied to
    plurals that end and that do not end in s. Contrast and compare
    with "most platform's." Turn over your test papers and begin
    writing ... NOW. Five minutes, neatness counts.
    Eric Sosman, Jul 13, 2013
  8. mathog

    Eric Sosman Guest

    The point you're missing is that one platform's headers are not
    portable to another platform, even if the interfaces they describe
    are. The bit-fields in the headers' structs (if they use them) are
    specific to the platform for which they were written, and will not
    necessarily work on other platforms, not even on *any* other platform.
    Offering bit-fields as a portable means to achieve an externally-
    defined format is folly: It may be possible to match the format on
    Platform P with Declaration D, but Declaration D could yield an
    entirely different format when compiled on Platform Q.
    Portability between multiple compilers for a single platform
    is occasionally of interest, typically when you're compiling your
    own source with Compiler A but using somebody else's binary library
    built with Compiler B. Such situations are far from unknown -- I've
    dealt with them often enough. (I recall once finding a SIGSEGV in
    a binary-only library whose supplier was not interested in fixing it,
    and using hex-mode Emacs to turn it into a slow memory leak instead.
    Not ideal, but better to let the balloon hiss slowly than go POP!)

    However, when people speak of "portability" it seems to me they
    are more usually concerned with portability between different systems,
    possibly running on different hardware. Development being expensive,
    one wants to produce code that can move with minimal effort from
    Windows to Linux to Solaris to OS/400, from x86 to x64 to ARM to
    Itanium to SPARC to PowerPC to ... If you want to match a dictated
    format on all these platforms and more, you should avoid bit-fields;
    in fact, you should avoid structs altogether for this purpose.
    Eric Sosman, Jul 13, 2013
  9. mathog

    James Kuyper Guest

    What I mean by "portable" is: works on systems that, because the
    standard doesn't mandate such a pragma, provides one with a syntax
    incompatible with the one you're used to using, or possibly don't even
    provide one at all. Also, "portable" means that it works on systems
    that, because the standard doesn't prohibit such padding, inserts some
    in locations where you mistakenly thought such padding could not be

    I find the standard's failure to more tightly specify struct layouts a
    big annoyance, and it's one of the first things I'd fix if I had to the
    power to do so - but you have to ignore history to declare it
    unnecessary. There's a reason the standard leaves those things
    unspecified: at the time it was first written, existing implementations
    differed radically in how such things were handled, and if the standard
    had specified those details, many implementations would have been able
    to conform only at the cost of breaking backward compatibility with
    existing binaries an existing data files. That's still true today. If
    and when this ever gets fixed, the costs are going to be huge.
    There's a small town in that bathwater - but it's still true, as far as
    truly portable code is concerned. If the variety of systems your
    software works on is small enough that you can get away with using
    structs to parse or create externally-specified data structures, then it
    wouldn't qualify as "truly portable" in my books.
    James Kuyper, Jul 13, 2013
  10. mathog

    Ian Collins Guest

    OK, time for me to sum up and shut up...

    Yes I generally agree with Eric's comment "structs are useless as a
    means of mapping an externally-defined format portably". I had a career
    changing moment many years ago when I had to get some 68K code running
    on SPARC. The code used packed structs to map protocol message packets.
    These had a single byte initial type field that caused all of the
    following data to be misaligned. Not a problem on 68K, but calamitous
    on SPARC! Getting that code to run on the Sun box without a rewrite was
    one of the most interesting challenges I've faced.

    While inappropriate for portable code, bit-fields do have a place in
    code that is inherently not portable, such as drivers or the platform
    specific layers in otherwise portable code. One example of the latter
    would be the lower layer packet manipulation in a socket or other
    network protocol library.
    On at platform where I am happy to use bit-fields I would uses them.
    Otherwise mask and shift.
    Ian Collins, Jul 14, 2013
  11. [...]

    And even the non-portable mechanisms can lead to unsafe code.

    For example, if you pack a structure so that an int member doesn't meet
    the CPU's alignment requirement, referring to the member directly will
    generally work, as the compiler generates whatever code is needed to
    make that work, but referring to it indirectly via an int* pointer can
    cause your program to crash.

    See this question and answer on Stack Overflow (both mine) for details
    about gcc's implementation of this:
    Keith Thompson, Jul 14, 2013
  12. mathog

    Eric Sosman Guest

    After a lengthy (and sometimes bordering on the rancorous)
    debate, I think a large part of my disagreement with Ian Collins
    comes down to a different slant on what "portable" means. Given
    some externally-defined layout involving items that aren't easily
    mapped to discrete bytes:

    - I maintain that you can't write a struct declaration using
    bit-fields that will match the desired layout on all platforms.
    I'm right, of course.

    - Ian holds that on any given platform odds are that there's a
    way to write a struct declaration using bit-fields that will
    yield the desired layout. He's right, of course.

    That is, I'm considering a specific declaration D and pointing
    out that it won't work on all platforms; "Therefore, bit-fields as
    a match for external formats are not portable." Meanwhile, Ian
    argues that there is a family of declarations D*, and that on any
    platform of interest some member of that family satisfies the
    requirements; "Therefore, bit-fields as a match for external
    formats are (almost certainly) portable." The whole thing comes
    down to point of view: The technique is very probably portable,
    even though specific instances are not so.

    Method versus instance -- that's the root of my misunderstanding.
    Eric Sosman, Jul 14, 2013
  13. mathog

    Ian Collins Guest

    Rancorous? This is Usenet! Any rancour on my part was unintentional.
    Ian Collins, Jul 14, 2013
  14. mathog

    Tim Rentsch Guest

    I don't agree. There are plenty of cases where you can, but
    also plenty of cases where you can't, even if we stipulate
    that the layouts are "natural", and that the platforms and
    compilers are mainstream (eg, x86 and gcc).

    To be fair, there are also plenty of cases where such fields
    can't be extracted by simple shifting and masking either.
    These things tend to depend on the impedance match between
    the layout and the underlying architecture -- some layouts
    just don't work very well on some architectures, and other
    layouts on others.
    Tim Rentsch, Jul 14, 2013
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.