3

假设我的项目包含来自 3rd 方库的标头,其中包含以下内容:

struct foo {
    signed int x:4;
};

如果不假设位字段的宽度始终为 4,并且不依赖于实现定义的行为,我如何确定可以存储在 member 中的最大值x

4

3 回答 3

5

由于无法用 计算位域的大小sizeof,这可以提供帮助:

#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;
}

左移直到f.x是负数。

编辑:

上面的代码是实现定义的,检查这个,我认为这会起作用(但你必须处理 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;
}

如您现在所见,它不超过2^(n-1)-1(适用于 a long

于 2013-07-20T07:28:34.120 回答
1

基本上你不能。问题与确定INT_MAXor相同INT_MIN:因为您无法自己确定这些,编译器实现必须提供这些值。(您可以做的所有事情来确定符号位的位置具有实现定义(甚至未定义)的行为:溢出、移位运算符)

对于位域,实现不能提供这些值,所以你被卡住了。

这是位域真的不应该的原因之一signed。位域仅用于位操作,仅用于浪费符号位。

如果你的领域是unsigned事情会很容易。您只需将其存储-1在其中,您将获得所有值,即“类型”的最大值。

于 2013-07-22T21:37:05.893 回答
0

如果我要这样做,我会尝试将 -1 加载到它,如果它是 2 的补码表示,那么它将是可以存储的最大正值。以上案例

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

其中一半是无符号最大值,一半+1是有符号最大值

于 2013-10-25T01:06:06.510 回答