2013-06-11 6 views
0

2 바이트를 하나의 부호없는 long 변수로 결합하려고합니다. 현재 코드가 작동하지 않습니다. MPLAB C18 컴파일러를 사용하고 있습니다. 이것이 제 코드입니다.2 바이트 배열을 부호없는 long 변수로 변환하는 방법은 무엇입니까?

unsigned long red = 0; 
    BYTE t[2]; 


    t[0] = 0x12; 
    t[1] = 0x33; 

    red = 100 * t[0] + t[1]; 
    printf("%lu", red); 

제 출력물로 1233이 표시되지 않는 이유를 알려주십시오.

+0

10 진수와 16 진수의 차이를 이해하지 못하는 것 같습니다 ... –

+0

무엇을 의미합니까? –

+0

2^8은 256 또는 0x100이며 100이 아닙니다! –

답변

1

배열의 값은 0x 접두어로 지정됩니다. 1000x100과 같지 않습니다.

컴파일러가 호환되지 않습니다. 또한 이진 연산자는 부호가있는 정수 유형의 경우 애매한 측면을 정의합니다 (이 중 BYTE 일 수 있음). 여기에 내가 안전을 위해, 그 코드를 작성하는 것입니다 방법은 다음과 같습니다 MPLAB C18는 C 표준에 약간의 이견을 가지고 모든 노트의

unsigned long red = 0; 
BYTE t[2]; 

t[0] = 0x12; 
t[1] = 0x33; 

red = (unsigned char) t[0]; 
red = red * 0x100; 
red = red + (unsigned char) t[1]; 

printf("Decimal: %lu\n" 
     "Hexadecimal: 0x%lx\n", red, red); 
+0

나는 빨간색에 대한 나의 가치로서 ** 4659 **를 얻고 있습니까? –

+0

맞습니다. 이게 뭐야? printf ("% lu \ n", 0x1233UL);' – Sebivor

+0

'100'은'0x100'과 같지 않다는 것을 기억하십시오. 마찬가지로 '1233'은 '0x1233'과 동일하지 않습니다. – Sebivor

5

256을 곱해야 할 때 t[0]100을 곱하면됩니다. 더 좋은 방법은 t[0]을 왼쪽으로 8 비트 이동하고 t[1]을 추가하는 것입니다.

red = (t[0] << 8) | t[1]; 
+0

이러한 방법 중 어느 것도 작동하지 않았습니다. 나는 ** 51 ** ** 더 나은 방법을 사용하여 빨간색을 얻고 있습니까? –

+2

@cookiemonster 16 진수는 여전히 십진수가 아닙니다. –

+1

'printf'를 수정하여 16 진수 값을 출력해야합니다. 당신은'printf ("% x", red)라고 말하고, – unxnut

0

첫째. user manual을 읽으십시오. 특히 "ISO divergences"라고 표시된 섹션 2.7을 읽어보십시오.

그래서 도 적용 문자 추진 대신 정수 승진을 리터럴 않는 C18에주의를 기울이십시오. 따라서 0x80과 0x80을 함께 추가하면 0x00이됩니다. 이를 방지하는 방법은 더 큰 상수가 필요한 경우 정상적으로 처리하는 방법과 동일합니다. 32 비트로 계산을 강제하려면 'L'또는 'UL'접미사를 사용하고, 필요할 경우에는 캐스트를 사용하십시오.

컴파일러의 최적화 프로그램이 다소 불완전 할 수 있습니다. 디스 어셈블리를 확인해야합니다. 32 비트 리터럴을 사용하면 8 비트 만 필요하더라도 32 비트 코드를 낼 수 있습니다. 당신은 문제가 비슷합니다, 당신은 기본적으로 작업에 게시 된 예에서

#define C8BIT ((unsigned char)(((0x12UL * 0x100UL) + 0xC0UL)>>6)) 

(그렇지 않으면 오버 플로우 것 그냥 예를 들어 임의의 계산) : 당신은 계산 등의 결과를 주조하여 주위에이 일을 할 수있다 unsigned chars를 사용하면 컴파일러는 unsigned char로 승격되며 최소 16 비트 깊이로 계산되어야합니다. 문제가있는 라인에 대한 적절한 청소 솔루션이 될 수 있습니다

red = (0x100UL * (unsigned long)(t[0])) + ((unsigned long)(t[1])); 

성능 문제가 있지만 (t 가정하면 [0] 그냥 거기에 몇 가지 예제 값을 가지고, 그래서 실제 프로그램에서 임의의 내용을 얻을 수있다 [1] t) 당신은 분해를 확인하고 마침내에 의지 할 수

red = (0x100U * t[0]) + t[1]; 

또는

red = (((unsigned short)(t[0]))<<8) + t[1]; 

(심지어) C18을 포함하여 온전한 컴파일러

다음에 적절한 결과를 제공해야합니다. 또한 C18은 최적화에 너무 강하지 않으며, 거기에 다중 루틴에 대한 라이브러리 호출을 포함 할 수 있으므로 버전이 변경되었습니다. 컴파일러가 올바르게 (0x100U는 16 비트 프로모션을 요구함) 컴파일러가 16 비트 로직을 추가하기 위해 컴파일러를 혼란스럽게 할 수도 있으므로 t [0]과 t [1]을 생략했습니다. C18은이 기간에 매우 약합니다!)와 리터럴 '0'피연산자로 구성됩니다. 성능이 중요한 경우 해체를 확인하십시오. 그렇지 않으면 깨끗한 솔루션으로 이동하십시오!

또한 BYTE 유형을 확인할 수도 있습니다. 서명되지 않은 char이어야하지만 꼭 그렇지는 않아야합니다. 일관된 사용을 위해 고정 된 크기 (예 : typedef unsigned char uint8; 정도)로 유형을 정의하고자 할 수 있습니다.