所以我在获取int字段然后签名扩展时遇到了一些麻烦。我有一个获取int的字段的方法。
getField(int value, int hi, int lo);
值是我从中获取字段的int,而hi和lo是字段的大小。
所以我可以在getFieldSignExtended(int value,int hi,int lo)中调用这个getField方法,但是如何进行符号扩展呢?
e.g。 value = 7, hi = 1, lo = 0
getField(7, 1, 0);
返回3,因为二进制中的7是111,而hi和lo取0到1的字段。
从getField返回3,我得到的值等于0x0003。
到目前为止我所做的事情与积极因素有关,但在消极因素上却大打折扣。当我说“搞砸”时,我的意思是它根本不起作用。因此,如果我尝试在-1上使用它,它会显示为一个大的int而不是一个负数。
感谢您的帮助! :
编辑:对不起我把自己和你们中的一些人搞糊涂了:P。固定的。
答案 0 :(得分:2)
这里的线路之间有很多阅读。但是,如果getField(7, 1, 0)
返回3并且您需要getFieldSignExtended(15, 2, 0)
返回-3
而getFieldSignExtended(3, 2, 0)
返回+3
,那么这可能就是您所追求的。< / p>
这个概念是你将n比特字段从原始值的比特hi:lo视为2的补码数。如果n位的第一位是1,那么您希望将n位字段视为负数。如果3位字段的第一位是0,那么您希望将其视为正数。
#include <assert.h>
#include <limits.h>
#include <stdio.h>
extern int getFieldSignExtended(int value, int hi, int lo);
enum { INT_BITS = CHAR_BIT * sizeof(int) };
int getFieldSignExtended(int value, int hi, int lo)
{
assert(lo >= 0);
assert(hi > lo);
assert(hi < INT_BITS - 1);
int bits = (value >> lo) & ((1 << (hi - lo + 1)) - 1);
if (bits & (1 << (hi - lo)))
return(bits | (~0U << (hi - lo)));
else
return(bits);
}
这3个断言是直截了当的;唯一有争议的是代码拒绝处理第31位。如果你用hi = 31和lo = 0调用它,那么shift(hi-lo + 1)太大而且行为是未定义的。您还会遇到正确移位负数的实现定义行为。通过采用无符号整数参数并且如果&
不执行hi - lo + 1 == INT_BITS
操作,可以解决这些问题。修复问题留给读者练习。
bits
的赋值将值右移,并用正确的位数掩盖它。 (1 << (hi - lo + 1)) - 1
将1向左移位比字段中的位数多1,然后减去1以为字段中的每个位位置生成二进制1的字符串。例如,对于hi = 2,lo = 0,这将1左移3位,产生二进制1000;减1表示0111,因此选择正确的3位。因此,bits
包含n位整数的适当位组。
if
测试检查是否设置了n位整数的最高位。如果未设置符号位,我们只返回值bits
。如果设置了符号位,那么我们需要执行一个棘手的计算 - 在这个答案的初稿中(非常)错误。假设我们有一个3位= 101的字段。作为3位2的补码数,表示-3。我们需要将所有1扩展到左侧以生成全尺寸-1
。 ~0
的值都是位1;当它向左移hi - lo
位时,它会为值的非符号位留下一系列零。如果向左移动hi - lo + 1
,它也会起作用,但+ 1
需要额外的计算,这是不必要的。
我使用此测试工具来确保代码工作正常。系统测试输出是严格的(在小数字上)。它确保计算的值与预期值匹配。 '详尽'测试并非真正详尽无遗;它只测试一个值,它更适用于观察问题(例如使用hi = 31和lo = 0在我的机器上给出错误的0答案)和模式。
static const struct
{
int value;
int hi;
int lo;
int wanted;
} tests[] =
{
{ 0x0F, 1, 0, -1 },
{ 0x0F, 2, 0, -1 },
{ 0x0F, 2, 1, -1 },
{ 0x0F, 3, 1, -1 },
{ 0x0F, 4, 2, +3 },
{ 0x0F, 5, 0, +15 },
{ 0x0F, 5, 1, +7 },
{ 0x0F, 5, 2, +3 },
{ 0x0F, 5, 3, +1 },
{ 0x0F, 5, 4, 0 },
{ 0x03, 2, 0, +3 },
{ 0xF3, 2, 0, +3 },
{ 0xF3, 3, 0, +3 },
{ 0xF3, 4, 0, -13 },
{ 0xF3, 5, 0, -13 },
{ 0xF3, 6, 0, -13 },
{ 0xF3, 7, 0, -13 },
{ 0xF3, 7, 1, -7 },
{ 0xF3, 7, 2, -4 },
{ 0xF3, 7, 3, -2 },
{ 0xF3, 7, 4, -1 },
{ 0xF3, 8, 0, 0xF3 },
};
enum { NUM_TESTS = sizeof(tests) / sizeof(tests[0]) };
static const char s_pass[] = "== PASS ==";
static const char s_fail[] = "!! FAIL !!";
static void systematic_test(void)
{
int fail = 0;
for (int i = 0; i < NUM_TESTS; i++)
{
char const *pf = s_fail;
int actual = getFieldSignExtended(tests[i].value, tests[i].hi, tests[i].lo);
if (actual == tests[i].wanted)
pf = s_pass;
else
fail++;
printf("%s GFSX(%+4d = 0x%.4X, %d, %d) = %+4d = 0x%.8X (wanted %+4d = 0x%.8X)\n",
pf, tests[i].value, tests[i].value, tests[i].hi, tests[i].lo, actual, actual,
tests[i].wanted, tests[i].wanted);
}
printf("%s\n", (fail == 0) ? s_pass : s_fail);
}
static void exhaustive_test(void)
{
int value = 0x5FA03CE7;
for (int i = 1; i < INT_BITS - 1; i++)
{
for (int j = 0; j < i; j++)
{
int actual = getFieldSignExtended(value, i, j);
printf("%11sGFSX(%d = 0x%X, %2d, %2d) = %+10d = 0x%.8X\n", "",
value, value, i, j, actual, actual);
}
}
}
int main(void)
{
int result1 = getFieldSignExtended(15, 2, 0);
int result2 = getFieldSignExtended( 3, 2, 0);
printf("GFSX(15, 2, 0) = %+d = 0x%.8X\n", result1, result1);
printf("GFSX( 3, 2, 0) = %+d = 0x%.8X\n", result2, result2);
printf("\nSystematic test\n");
systematic_test();
printf("\nExhaustive test\n");
exhaustive_test();
return(0);
}
这是穷举测试前测试代码的输出,加上穷举测试的一小部分输出:
GFSX(15, 2, 0) = -1 = 0xFFFFFFFF
GFSX( 3, 2, 0) = +3 = 0x00000003
Systematic test
== PASS == GFSX( +15 = 0x000F, 1, 0) = -1 = 0xFFFFFFFF (wanted -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 2, 0) = -1 = 0xFFFFFFFF (wanted -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 2, 1) = -1 = 0xFFFFFFFF (wanted -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 3, 1) = -1 = 0xFFFFFFFF (wanted -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 4, 2) = +3 = 0x00000003 (wanted +3 = 0x00000003)
== PASS == GFSX( +15 = 0x000F, 5, 0) = +15 = 0x0000000F (wanted +15 = 0x0000000F)
== PASS == GFSX( +15 = 0x000F, 5, 1) = +7 = 0x00000007 (wanted +7 = 0x00000007)
== PASS == GFSX( +15 = 0x000F, 5, 2) = +3 = 0x00000003 (wanted +3 = 0x00000003)
== PASS == GFSX( +15 = 0x000F, 5, 3) = +1 = 0x00000001 (wanted +1 = 0x00000001)
== PASS == GFSX( +15 = 0x000F, 5, 4) = +0 = 0x00000000 (wanted +0 = 0x00000000)
== PASS == GFSX( +3 = 0x0003, 2, 0) = +3 = 0x00000003 (wanted +3 = 0x00000003)
== PASS == GFSX(+243 = 0x00F3, 2, 0) = +3 = 0x00000003 (wanted +3 = 0x00000003)
== PASS == GFSX(+243 = 0x00F3, 3, 0) = +3 = 0x00000003 (wanted +3 = 0x00000003)
== PASS == GFSX(+243 = 0x00F3, 4, 0) = -13 = 0xFFFFFFF3 (wanted -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 5, 0) = -13 = 0xFFFFFFF3 (wanted -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 6, 0) = -13 = 0xFFFFFFF3 (wanted -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 7, 0) = -13 = 0xFFFFFFF3 (wanted -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 7, 1) = -7 = 0xFFFFFFF9 (wanted -7 = 0xFFFFFFF9)
== PASS == GFSX(+243 = 0x00F3, 7, 2) = -4 = 0xFFFFFFFC (wanted -4 = 0xFFFFFFFC)
== PASS == GFSX(+243 = 0x00F3, 7, 3) = -2 = 0xFFFFFFFE (wanted -2 = 0xFFFFFFFE)
== PASS == GFSX(+243 = 0x00F3, 7, 4) = -1 = 0xFFFFFFFF (wanted -1 = 0xFFFFFFFF)
== PASS == GFSX(+243 = 0x00F3, 8, 0) = +243 = 0x000000F3 (wanted +243 = 0x000000F3)
== PASS ==
Exhaustive test
GFSX(1604336871 = 0x5FA03CE7, 1, 0) = -1 = 0xFFFFFFFF
GFSX(1604336871 = 0x5FA03CE7, 2, 0) = -1 = 0xFFFFFFFF
GFSX(1604336871 = 0x5FA03CE7, 2, 1) = -1 = 0xFFFFFFFF
GFSX(1604336871 = 0x5FA03CE7, 3, 0) = +7 = 0x00000007
GFSX(1604336871 = 0x5FA03CE7, 3, 1) = +3 = 0x00000003
GFSX(1604336871 = 0x5FA03CE7, 3, 2) = +1 = 0x00000001
GFSX(1604336871 = 0x5FA03CE7, 4, 0) = +7 = 0x00000007
GFSX(1604336871 = 0x5FA03CE7, 4, 1) = +3 = 0x00000003
GFSX(1604336871 = 0x5FA03CE7, 4, 2) = +1 = 0x00000001
GFSX(1604336871 = 0x5FA03CE7, 4, 3) = +0 = 0x00000000
GFSX(1604336871 = 0x5FA03CE7, 5, 0) = -25 = 0xFFFFFFE7
GFSX(1604336871 = 0x5FA03CE7, 5, 1) = -13 = 0xFFFFFFF3
GFSX(1604336871 = 0x5FA03CE7, 5, 2) = -7 = 0xFFFFFFF9
GFSX(1604336871 = 0x5FA03CE7, 5, 3) = -4 = 0xFFFFFFFC
GFSX(1604336871 = 0x5FA03CE7, 5, 4) = -2 = 0xFFFFFFFE
GFSX(1604336871 = 0x5FA03CE7, 6, 0) = -25 = 0xFFFFFFE7
GFSX(1604336871 = 0x5FA03CE7, 6, 1) = -13 = 0xFFFFFFF3
GFSX(1604336871 = 0x5FA03CE7, 6, 2) = -7 = 0xFFFFFFF9
GFSX(1604336871 = 0x5FA03CE7, 6, 3) = -4 = 0xFFFFFFFC
GFSX(1604336871 = 0x5FA03CE7, 6, 4) = -2 = 0xFFFFFFFE
GFSX(1604336871 = 0x5FA03CE7, 6, 5) = -1 = 0xFFFFFFFF
...
GFSX(1604336871 = 0x5FA03CE7, 29, 28) = +1 = 0x00000001
GFSX(1604336871 = 0x5FA03CE7, 30, 0) = -543146777 = 0xDFA03CE7
GFSX(1604336871 = 0x5FA03CE7, 30, 1) = -271573389 = 0xEFD01E73
GFSX(1604336871 = 0x5FA03CE7, 30, 2) = -135786695 = 0xF7E80F39
GFSX(1604336871 = 0x5FA03CE7, 30, 3) = -67893348 = 0xFBF4079C
GFSX(1604336871 = 0x5FA03CE7, 30, 4) = -33946674 = 0xFDFA03CE
GFSX(1604336871 = 0x5FA03CE7, 30, 5) = -16973337 = 0xFEFD01E7
GFSX(1604336871 = 0x5FA03CE7, 30, 6) = -8486669 = 0xFF7E80F3
GFSX(1604336871 = 0x5FA03CE7, 30, 7) = -4243335 = 0xFFBF4079
GFSX(1604336871 = 0x5FA03CE7, 30, 8) = -2121668 = 0xFFDFA03C
GFSX(1604336871 = 0x5FA03CE7, 30, 9) = -1060834 = 0xFFEFD01E
GFSX(1604336871 = 0x5FA03CE7, 30, 10) = -530417 = 0xFFF7E80F
GFSX(1604336871 = 0x5FA03CE7, 30, 11) = -265209 = 0xFFFBF407
GFSX(1604336871 = 0x5FA03CE7, 30, 12) = -132605 = 0xFFFDFA03
GFSX(1604336871 = 0x5FA03CE7, 30, 13) = -66303 = 0xFFFEFD01
GFSX(1604336871 = 0x5FA03CE7, 30, 14) = -33152 = 0xFFFF7E80
GFSX(1604336871 = 0x5FA03CE7, 30, 15) = -16576 = 0xFFFFBF40
GFSX(1604336871 = 0x5FA03CE7, 30, 16) = -8288 = 0xFFFFDFA0
GFSX(1604336871 = 0x5FA03CE7, 30, 17) = -4144 = 0xFFFFEFD0
GFSX(1604336871 = 0x5FA03CE7, 30, 18) = -2072 = 0xFFFFF7E8
GFSX(1604336871 = 0x5FA03CE7, 30, 19) = -1036 = 0xFFFFFBF4
GFSX(1604336871 = 0x5FA03CE7, 30, 20) = -518 = 0xFFFFFDFA
GFSX(1604336871 = 0x5FA03CE7, 30, 21) = -259 = 0xFFFFFEFD
GFSX(1604336871 = 0x5FA03CE7, 30, 22) = -130 = 0xFFFFFF7E
GFSX(1604336871 = 0x5FA03CE7, 30, 23) = -65 = 0xFFFFFFBF
GFSX(1604336871 = 0x5FA03CE7, 30, 24) = -33 = 0xFFFFFFDF
GFSX(1604336871 = 0x5FA03CE7, 30, 25) = -17 = 0xFFFFFFEF
GFSX(1604336871 = 0x5FA03CE7, 30, 26) = -9 = 0xFFFFFFF7
GFSX(1604336871 = 0x5FA03CE7, 30, 27) = -5 = 0xFFFFFFFB
GFSX(1604336871 = 0x5FA03CE7, 30, 28) = -3 = 0xFFFFFFFD
GFSX(1604336871 = 0x5FA03CE7, 30, 29) = -2 = 0xFFFFFFFE
答案 1 :(得分:0)
您可以采取多种方法。如果刚刚开始,你可以算术计算字段中的位数。所以,例如:
if (value %2 >= 1)
{
// you know that the value has a `1` as the lest significant digit.
// if that's one of the digits you're looking for, you can do something like count++ here
}
else
{
// least significant digit is a '0'
}
然后
if (value % 4 >=2)
{
// you know that the second least significant digit is `1`
// etc.
}
如果你这样做,你可能希望将它们变成某种循环。
现在,更好的方法是使用按位和,如下所示:
if (value & 8 != 0)
// here you know that the fourth least significant digit (the one representing 8) is 1.
// do a Google search on bitwise anding to get more information.