Search code examples
cportabilitybit-fieldscc

Bit fields portability in a shared library


I have difficulty to understand the portability of bit fields in C. Imagine I have a shared library composed of only two files, libfoobar.h (the public header) and libfoobar.c, with the following simple content:

libfoobar.h:

typedef struct some_bitfield_T {
    unsigned char foo:3;
    unsigned char bar:2;
    unsigned char tree:2;
    unsigned char window:1;
} some_bitfield;

extern unsigned int some_function (some_bitfield input);

libfoobar.c:

#include "libfoobar.h"

unsigned int some_function (some_bitfield input) {
    return input.foo * 3 + input.bar + input.tree + 1 - input.window;
}

After having compiled and installed the library, I test it with a program named test.

test.c:

#include <stdio.h>
#include <libfoobar.h>

int main () {
    some_bitfield my_attempt = {
        .foo = 6,
        .bar = 3,
        .tree = 1,
        .window = 1
    };
    unsigned int some_number = some_function(my_attempt);
    printf("Here is the result: %u\n", some_number);
    return 0;
}

Is there any possibility that the test program above will produce anything different than the following output?

Here is the result: 22

If yes, when? What if the library is compiled by someone else other than me? What if I use different compilers for the library and the test program?


Solution

  • Bitfields are implementation defined and not not portable. But for most relevant platforms, their extraction/packing is well specified by the ABI so that they can be safely used in shared libraries.

    E.g.:

    • ARM EABI specifies them in 7.1.7 "Bit-fields".
    • i386 ABI specifies them on page 3-6+
    • x86-64 specifies them on page 15+
    • MIPS specifies them on page 3-7+