선이 여기에 무슨 사이 읽기의 엄청 많이있다. 그러나 getField(7, 1, 0)
이 3을 반환하고 -3
및 getFieldSignExtended(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
'는 제로로 연장 로그인하면 "모순이다 . '부호 확장'은 '부호 비트 (0 또는 1)를 확장자에 복사'; 0으로 확장하는 것은 유형이 부호가없고 확장 된 경우에 일어납니다. –
문제가 제대로 지정되지 않았으므로 이것이 "진짜 질문이 아님"으로 표시된 "닫히는"위험이 있습니다. 또한 어떤 접근 방식을 시도해 보셨습니까? – Kaz
예제에서 부호 확장은 -1을 반환하는 것을 의미 할 수 있습니다. 왜냐하면 우리가 '0000111'에서 '11'비트를 가져 오는 경우 '11'을 -1로 나타내는 2 비트 2의 보수 값으로 해석해야하기 때문입니다 . C의 2의 보수 플랫폼에서, 2 비트 너비 인 signed struct/union 비트 필드는 '11'을 포함하여 -1로 평가됩니다. – Kaz