2012-12-07 43 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