Search code examples
cgccbit-fieldstypeof

GNU C replacement/workaround for typeof/__auto_type applied to bit fields


GNU C has two extensions that it proposes to make safe macros like MAX and MIN that will evaluate arguments only once: typeof and __auto_type. To give examples of two MAX macros demonstrating each one:

#define MAX(a, b) ({    \
    typeof(a) _a = (a); \
    typeof(b) _b = (b); \
    _a > _b ? _a : _b;  \
})

#define MAX(a, b) ({      \
    __auto_type _a = (a); \
    __auto_type _b = (b); \
    _a > _b ? _a : _b;    \
})

The problem with both of these is that typeof and __auto_type give errors if it is used on a bit field. This example code shows the problems with a bit field using either MAX:

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

// Insert one of the MAX macros here

struct bitfields {
    uint8_t a: 4;
    uint8_t b: 4;
};

int main(int argc, char *args[]) {
    struct bitfields x = {12, 4};
    printf("%d\n", MAX(x.a, x.b));
    return 0;
}

GCC gives these error messages for typeof and __auto_type, respectively:

error: 'typeof' applied to a bit-field
error: '__auto_type' used with a bit-field initializer

So the question is: Why does GCC not allow these to be used with bit fields (I can't find any documentation on it), and what can be done to make a MAX macro that evaluates arguments only once for any type that still works with bit fields?


Solution

  • You use __typeof__(+(a)) to get the promoted type according to default promotions. This will work at least for bitfields of type int. I'm not sure how compilers treat the type for larger bitfield types, which are implementation-defined.