2012-12-07 3 views
1

그래서 나는 int 필드를 가져 와서 그것을 확장하는 데 문제가 있습니다. 나는 int의 필드를 얻는 메소드를 가지고있다.로그인 C에서 int 확장

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

값은 내가 필드를 가져 오는 int이며, hi와 lo는 필드의 크기입니다.

그래서이 getField 메소드를 getFieldSignExtended (int 값, int hi, int lo) 내부에서 호출 할 수 있습니다. 그러나 이것을 확장하는 방법에 대해 어떻게 설명합니까?

value = 7, hi = 1, lo = 0

getField(7, 1, 0); 반환 3 이진 7 (111) 및 하이이고 3 I 그 값이 동일하다 0x0003 얻을 getField로부터 리턴되는 LO 1.

0의 필드를 가지고 있기 때문이다.

나는 지금까지 긍정적 인 반응을 보였지만 네거티브를 크게 빗나갔습니다. 그리고 내가 "엉망"이라고 말하면 나는 그것이 전혀 작동하지 않는다는 것을 의미합니다. 그래서 -1에 사용하려고하면 음수 대신 큰 int로 표시됩니다.

도움 주셔서 감사합니다. :]

편집 : 죄송합니다. 나는 혼란스럽고 일부는 당신과 모순 된 진술을합니다. P. 결정된.

+3

'는 제로로 연장 로그인하면 "모순이다 . '부호 확장'은 '부호 비트 (0 또는 1)를 확장자에 복사'; 0으로 확장하는 것은 유형이 부호가없고 확장 된 경우에 일어납니다. –

+0

문제가 제대로 지정되지 않았으므로 이것이 "진짜 질문이 아님"으로 표시된 "닫히는"위험이 있습니다. 또한 어떤 접근 방식을 시도해 보셨습니까? – Kaz

+0

예제에서 부호 확장은 -1을 반환하는 것을 의미 할 수 있습니다. 왜냐하면 우리가 '0000111'에서 '11'비트를 가져 오는 경우 '11'을 -1로 나타내는 2 비트 2의 보수 값으로 해석해야하기 때문입니다 . C의 2의 보수 플랫폼에서, 2 비트 너비 인 signed struct/union 비트 필드는 '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. 
} 

당신이 그런 식으로 그것을 할 경우, 당신은 아마 어떤 종류의 루프에 그 일을 할 것입니다.

이제 그것을 할 수있는 더 좋은 방법은 다음과 같이 비트 AND 연산을 사용하고 있습니다 :

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

스택 오버플로에 오신 것을 환영합니다. 귀하의 대답은 제기 된 문제에 대한 완전한 해결책을 제공하지 못하며, 이는 제한된 가치를 의미합니다. 내가 말한 것을 어떻게 해결하여 문제를 해결할 것인지 계획하는 방법이 내게는 분명하지 않습니다. 일반적으로 SO에 대한 좋은 대답은 완전하거나 쉽게 완성 될 것입니다. 당신이 질문에 대해 좋은 대안을 가지고 있다면 (그것은 해석이 필요하고 별의 문제는 아닙니다), 대안 답을 보는 것이 좋을 것입니다. –

2

선이 여기에 무슨 사이 읽기의 엄청 많이있다. 그러나 getField(7, 1, 0)이 3을 반환하고 -3getFieldSignExtended(3, 2, 0)을 반환하는 경우 getFieldSignExtended(15, 2, 0)이 필요하면 +3을 반환하는 것이 좋습니다.

개념은 원래 값의 비트 hi : lo에서 n 비트 필드를 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 시프트 한 다음 필드의 각 비트 위치에 대해 2를 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입니다.비트만큼 왼쪽으로 시프트되면 값의 부호없는 비트에 대해 일련의 0이 남습니다. 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 
관련 문제