2012-12-07 44 views
1

所以我有一些麻烦得到一个int的字段,然后签名扩展它。我有一个方法获取int的字段。符号在C中扩展int int

getField(int value, int hi, int lo); 

值是我从一个字段中取得的整数,hi和lo是字段的大小。

所以我可以调用getFieldSignExtended(int值,int hi,int lo)里面的getField方法,但是如何去扩展它的符号呢?

例如value = 7, hi = 1, lo = 0

getField(7, 1, 0);返回3,因为以二进制7是111和HI和LO取0领域1.

随着从getfield命令返回3我得到的值等于为0x0003。

我到目前为止的工作都是积极的,但是对消极方面却大打折扣。当我说“搞砸”时,我的意思是它根本不起作用。所以如果我尝试在-1上使用它,它会显示为一个大的int值而不是负值。

感谢您的帮助! :]

编辑:对不起,我混淆了我自己和你们中的一些人的矛盾声明:P。固定。

+3

“符号扩展用零”是自相矛盾的。 '符号扩展'表示'将符号位(0或1)复制到扩展名';只用零来扩展它,如果类型是无符号和扩展的话会发生什么。 –

+0

您的问题未指定,因此有可能被标记为“关闭”为“不是真正的问题”。另外,你尝试过什么方法? – Kaz

+0

你的例子中的符号扩展可能意味着返回-1,因为如果我们从'... 0000111'中取出'11'位,我们必须将'11'解释为一个两位二进制补码值,它代表-1 。在C中,在一个二进制补码平台上,一个带符号的结构/联合位域是两位宽,其中保存“11”的结果为-1。 – Kaz

回答

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. 
+0

欢迎来到Stack Overflow。您的回答并不能提供解决问题的完整解决方案,这意味着它的价值有限。我不完全清楚你打算如何扩展你所说的解决问题的方法。一般来说,关于SO的一个好的答案要么是完整的要么是容易完成的。如果你对这个问题有一个很好的替代解释(这确实需要解释;这不是一个很好的问题),那么看到你的替代答案会很棒。 –

2

有很多可怕的行会在这里阅读之间。但是,如果getField(7, 1, 0)返回3,并且您需要getFieldSignExtended(15, 2, 0)返回-3getFieldSignExtended(3, 2, 0)以返回+3,那么这可能就是您要的。

这个概念是,你把一个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调用它,那么移位(hi-lo + 1)太大,行为不确定。您还会遇到右移一个负数的实现定义的行为。通过采用无符号整数参数可以解决这些问题,并且如果hi - lo + 1 == INT_BITS不执行&操作。解决这些问题留给读者来练习。

bits的赋值将值右移,并用正确的位数屏蔽它。 (1 << (hi - lo + 1)) - 1移位1比字段中的位数多1,然后减1,为字段中的每个位位置生成一串二进制1。例如,对于hi = 2,lo = 0,这将左移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