假设我的项目包含来自 3rd 方库的标头,其中包含以下内容:
struct foo {
signed int x:4;
};
如果不假设位字段的宽度始终为 4,并且不依赖于实现定义的行为,我如何确定可以存储在 member 中的最大值x
?
假设我的项目包含来自 3rd 方库的标头,其中包含以下内容:
struct foo {
signed int x:4;
};
如果不假设位字段的宽度始终为 4,并且不依赖于实现定义的行为,我如何确定可以存储在 member 中的最大值x
?
由于无法用 计算位域的大小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
)
基本上你不能。问题与确定INT_MAX
or相同INT_MIN
:因为您无法自己确定这些,编译器实现必须提供这些值。(您可以做的所有事情来确定符号位的位置具有实现定义(甚至未定义)的行为:溢出、移位运算符)
对于位域,实现不能提供这些值,所以你被卡住了。
这是位域真的不应该的原因之一signed
。位域仅用于位操作,仅用于浪费符号位。
如果你的领域是unsigned
事情会很容易。您只需将其存储-1
在其中,您将获得所有值,即“类型”的最大值。
如果我要这样做,我会尝试将 -1 加载到它,如果它是 2 的补码表示,那么它将是可以存储的最大正值。以上案例
foo.x = -1; unsigned int max_size = (unsigned int)(foo.x);
其中一半是无符号最大值,一半+1是有符号最大值