printf, sscanf 16진 데이터 변환 문제


문제1: 원래 프로그램의 목적은 문자열 형식의 맥 주소를char형 수조에 저장하는 것이다(더 좋은 획득 방법이 있으면 메시지를 남겨주시면 고맙습니다). 코드는 다음과 같다. 맥이 다음 코드를 실행한 후 변수 int형 값이 바뀌었다.
#include 

typedef unsigned int uint32;

int main(void)
{
    int num = 1;
    char str_mac[] = "7f:ab:ee:af:55:76";
    unsigned char mac[6] = {0};

    printf("num = %d
", num); sscanf((char *)str_mac, "%2x:%2x:%2x:%2x:%2x:%2x", (uint32 *)&mac[0],(uint32 *)&mac[1],(uint32 *)&mac[2],(uint32 *)&mac[3],(uint32 *)&mac[4],(uint32 *)&mac[5]); printf("&mac[5] = %p; &num = %p
", &mac[5], &num); printf("num = %d
", num); printf("mac : [%x:%x:%x:%x:%x:%x]
", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); return 0; }
실행 결과는 다음과 같습니다.
➜  sscanf  ./a.out 
num = 1
&mac[5] = 0x7fff586b6897; &num = 0x7fff586b6898
num = 0
mac : [7f:ab:ee:af:55:76]

왜냐하면 x가 unsigned int형 바늘과 일치하기 때문에 맥[5] 주소에 값을 부여할 때 맥[5]을 시작하는 네 바이트에 값을 부여하여 변수 i의 값에 영향을 주었다.
수정된 코드는 다음과 같습니다.
int main(void)
{
    int num = 1;
    char str_mac[] = "7f:ab:ee:af:55:76";
    unsigned int tmp_mac[6] = {0};
    unsigned char mac[6] = {0};
    int i = 0;

    printf("num = %d
", num); sscanf((char *)str_mac, "%2x:%2x:%2x:%2x:%2x:%2x", (uint32 *)&tmp_mac[0],(uint32 *)&tmp_mac[1],(uint32 *)&tmp_mac[2],(uint32 *)&tmp_mac[3],(uint32 *)&tmp_mac[4],(uint32 *)&tmp_mac[5]); for (i = 0; i < sizeof(mac); i++) { mac[i] = tmp_mac[i]; } printf("num = %d
", num); printf("mac : [%x:%x:%x:%x:%x:%x]
", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); return 0; }

문제2: 다음 절차를 수행합니다.
#include 

int main(void)
{
    char a = 0xbf;
    printf("char_a = %2x 
", a); unsigned char ua = 0xbf; printf("unsigned_char_a = %2x
", ua); char b = 0x7f; printf("char_b = %2x
", b); int c = 0xbf; printf("int_c = %2x
", c); int d = 0x7f; printf("int_d = %2x
", d); return 0; }

실행 결과는 다음과 같습니다.
➜  hex  ./a.out 
char_a = ffffffbf 
unsigned_char_a = bf 
char_b = 7f 
int_c = bf 
int_d  = 7f 

왜chara 인쇄된 값 앞에 ffff가 많아졌고 다른 것은 모두 원하는 인쇄값입니다.
변수 유형의 수치 범위를 주의하지 않았기 때문입니다!
char형 변수의 수치 범위는 (-128127) 이다.한편, 0xbf의 값은 191로 그 범위 크기를 넘어섰다. 실제 대응하는 십진수 값은 65이고 음수는 컴퓨터에 부호화 형식으로 저장된다.
printf가 요구하는 출력 형식은% x 이고 그에 대응하는 변수 형식은 unsigned int이기 때문에 - 65는 unsigned int 형식으로 해석합니다.
- 65는 다음과 같이 컴퓨터에 표시됩니다.
1, 0000 0000 0000 0000 0000 0000 0100 0001 먼저 반격 1111 1111 1111 1111 111111 1111 1111 1011 1110
2. 위의 전환을 토대로 1을 더하면 1111 1111 1111 1111 1111 1011 1111
3. 위 컴퓨터의 저장 형식을 unsigned int에 따라 해석한 값은 ffffbf이다
참조 링크:
http://www.ruanyifeng.com/blog/2009/08/twos_complement.html

좋은 웹페이지 즐겨찾기