TEUS.me

 
 

 

대부분의 컴퓨터 언어에서 16진수 문자열을 숫자로 변환해주는 HEX2DEC() 함수를 지원한다.

엑셀이나 매틀랩 등은 물론이고, PHP에서도 지원된다.

윈도우10에 내장된 계산기에선 더욱 손쉽게 이를 처리해준다.

 

그런데, 막상 C언어에서 이를 사용하려면 아주 쉽게는 되지 않는다.

기능이 없는 것은 아닌데, 위에서 언급한 언어/환경에 비해선 뭔가 손이 좀 더 간다.

 

1. sscanf()

물론, C언어의 표준 함수인 sscanf() 함수로 이를 처리할 수 있다.

깔끔하게 처리가 가능하다.

char hex_text[] = "1A2B";
int val;
sscanf(hex_text, "%X", &val);
printf("%d\n", val);

 

2. 직접 작성-1

그런데, 여러가지 이유로 직접 이 기능을 구현해야 할 필요가 있다.

더 빠른 동작의 함수가 필요하거나, 마이컴에서 좀 더 작은 실행파일이 필요[각주:1]하거나 등등.

 

대략 아래와 같은 방식으로 작성할 것이다.

long hex2dec(char * a) {
  char c;
  long ret = 0;
  
  while (*a) {
    c = *a++;

    if (c >= '0' && c <= '9') {
      c -= '0';
    } else if (c >= 'a' && c <= 'f') {
      c = (c - 'a') + 10;
    } else if (c >= 'A' && c <= 'F') {
      c = (c - 'A') + 10;
    } else {
      return ret;
    }

    ret = (ret << 4) + c;
  }

  return ret;
}

 

이 코드는 잘 동작하지만, 뭔가 좀 찝찝한 구석이 있다.

비교 연산자가 너무 많이 사용되는 것.

물론, 요즘 컴퓨팅 환경이 이 정도의 비교 구문은 손쉽게 처리하긴 하지만, 뭔가 아쉽다.

 

3. 직접 작성-2

최근 메모장2 업데이트 중 Simplify hexadecimal number conversions이란 내용이 있었다.

위의 코드와 유사한 코드를 대폭 최적화한 내용이었다.

이 코드의 골자는 두 가지다.

 

- signed와 unsigned의 차이를 이용해서 비교 구문을 줄임

- or(|) 연산자를 활용해서 대소문자를 한번에 처리

 

이 내용을 적용한 코드는 다음과 같다.

long hex2dec(char * a) {
  char c;
  unsigned char diff;
  long ret = 0;
  
  while (*a) {
    c = *a++;

    diff = c - '0';
    if (diff > 9) {
      diff = (c | 0x20) - 'a';
      if (diff > 5) {
        return ret;
      }
      diff += 10;
    }

    ret = (ret << 4) + diff;
  }

  return ret;
}

 

 

  1. PC 환경과는 달리 마이컴 환경은 실행 파일의 크기를 극단적으로 줄여야 함 [본문으로]

공유하기

facebook twitter kakaoTalk kakaostory naver band

댓글

비밀글모드

  1. 흥미로운 주제 입니다 ㅎㅎ ... 임베디드 장치 프로그래밍을 하는 사람들이 아닌 경우엔 최근엔 이런거 고민하는 경우가 드물죠..
    저도 예전에 이런저런 장치 만들던 시절에 .. 몇달을 만들어온걸 원가 줄인다고 램 용량이 줄면서 x똥 싸본 적이 있어서..
    마이컴이라.. 아련~~합니다 ㅎㅎ
    2021.01.18 16:36 신고
    • 요즘은 아무래도 컴퓨팅 파워가 무한히(?) 올라가서 이런 고민을 많이들 하지 않는 것 같아요.
      사실 이런 부분도 중요한 부분인데 말입니다. ㅎㅎ
      2021.01.20 11:45 신고