Question

Suppose my project includes a header from a 3rd party library that contains this:

struct foo {
    signed int x:4;
};

Without assuming that the bit-field will always have width 4, and without relying on implementation-defined behavior, how can I determine the maximum value that can be stored in member x?

Was it helpful?

Solution 2

Basically you can't. The issue is the same as for determining INT_MAX or INT_MIN: because you can't determine these yourself, the compiler implementation has to provide these values. (All you could do to determine the position of the sign bit has implementation defined (or even undefined) behavior: overflow, shift operators)

For bitfields the implementation can't provide these values, so you are stuck.

This is one of the reasons bitfields really shouldn't be signed. Bitfields are for bit manipulations and nothing else, the sign bit is then just wasted.

If your field would be unsigned things would be easy. You'd just have to store -1 in it and you'd get the value with all ones, the maximum value for the "type".

OTHER TIPS

Since size of a bitfield it can't be calculated with sizeof, this can help:

#include <stdio.h>

struct foo {
    signed int x: 4;
};

#define BIT(n) (1l << (n))
#define BIT_MASK(len) (BIT(len) - 1)

int main(void)
{
    struct foo f = {0};
    long i = 0;

    while (f.x >= 0) {
        f.x = BIT_MASK(++i);
    }
    printf("bits=%ld max=%ld\n", i, BIT_MASK(i));
    return 0;
}

Left shift until f.x is negative.

EDIT:

The above code is implementation-defined, check this one, I think this will work (but you have to deal with BIG ENDIAN):

#include <stdio.h>
#include <string.h>

struct foo {
    signed int x: 4;
};

#define BIT(n) (1l << (n))
#define BIT_MASK(len) (BIT(len) - 1)

int main(void)
{
    long x, i = 0;
    struct foo f;

    f.x = -1;
    memcpy(&x, &f, sizeof(f));
    while (1) {
        if (!(x & BIT(++i))) break; 
    }
    printf("bits=%ld max=%ld\n", i, BIT_MASK(i));
    return 0;
}

As you can see now it doesn't exceeds 2^(n-1)-1 (works on a long)

If I were to do this, I would have tried loading a -1 to it and if it is a 2's complement representation then it would be the maximum positive value that can be stored. Above case

foo.x = -1; unsigned int max_size = (unsigned int)(foo.x);

half of it will be unsigned max, half+1 will be the signed max

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top