3

I am looking at a simple C function created by Tibor Kiss (link below). I am trying to understand how converting a single binary byte to two hex characters involves the addition of 'W' (0x57). Why is this being done?

I understand that >> shifts the character c right by four places (filling in the lefthand bits with 0's). I also understand the x=c&0x0f part which just masks the upper four bits of x using bitwise AND.

I just don't know why converting a binary byte to hexidecimal would involve adding ASCII 'W' (0x57).

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en543105

/******************************************************************************
 * Function:        void btoh(unsigned char c,char *str)
 *
 * PreCondition:    None
 *
 * Input:           str - pointer to the zero terminated string
 *                  c   - byte to convert
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Convert one byte to a 2 character length hexadecimal
 *                  zero terminated string
 *
 * Note:            Using static variable for less code size
 *****************************************************************************/
void btoh(unsigned char c,char *str)
{
    static unsigned char x;
    x=c>>4;
    *str=x+(x>9?'W':'0');
    x=c&0x0f;
    str[1]=x+(x>9?'W':'0');
    str[2]=0;
}
JJBladester
  • 51
  • 1
  • 2
  • 9

2 Answers2

9

The reason he adds 'W' is that he simplified this expression:

*str=x+(x>9? ('a'-10) :'0');

He observed that 'W' is 'a'-10, and entered the simplified constant into his code. This is not a very good idea, because it is hard to understand what is going on without looking at the ASCII table. Besides, the compiler simplifies the 'a'-10 expression to the same exact value anyway, so the readability is lost with no particular gains of any kind.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Just figured this out. Why on Earth would anyone do this? –  Aug 11 '13 at 21:44
  • @H2CO3 it's not an uncommon way to do it. – Keith Nicholas Aug 11 '13 at 21:46
  • 2
    @KeithNicholas I mean, `'a' - 10` is a constexpr. If my compiler didn't optimize it to literal `0x57`, I would eject it into outer space immediately. –  Aug 11 '13 at 21:49
  • 1
    @H2CO3 You may want to clarify that the last "it" refers to your compiler, not to the literal :-) – Sergey Kalinichenko Aug 11 '13 at 21:50
  • @dasblinkenlight How did you know? :D –  Aug 11 '13 at 21:50
  • 1
    @H2CO3 Why, the outer space is littered with bad compilers :-) – Sergey Kalinichenko Aug 11 '13 at 21:51
  • @H2CO3: same here. I remember the time when we disassembled the bios/monitor/OS for the Commodore-16 (excellent work by Bill G., IIRC) and traced the '@' // ox40 routine to format_as_hex. There was a '0' // 0x30, involved, too, IIRC. And maybe some other literals. **but never a 'W'** PLEASE STOP THAT!! – wildplasser Aug 11 '13 at 22:07
0

if c is (H1H2H3H4L1L2L3L4) ,str[0] has the 0000H1H2H3H4 , and str[1] has 0000L1L2L3L4

+ '0'                                             ANSI

0000 0*** + 0011 0000 = 0011 0****  0  -->  0x30   0
                                    1  -->  0x31   1
                                    2  -->  0x32   2
                                       ...
+'W'                                               ANSI
00001011 + 0101 0111 =  0110 0010   B  -->  0x62  -->b
00001100 + 0101 0111 =  0110 0011   C  -->  0x63  -->c
00001010 + 0101 0111 =  0110 0001   A  -->  0x61  -->a
00001101 + 0101 0111 =  0110 0100   D  -->  0x64  -->d
00001111 + 0101 0111 =  0110 0110   F  -->  0x66  -->f
00001110 + 0101 0111 =  0110 0101   E  -->  0x65  -->e

So he just turn

                0x12 to '1''2'0
                0xAB to 'a''b'0
Lidong Guo
  • 2,817
  • 2
  • 19
  • 31