-2

My Challenge is to convert hex value to ascii, the input is a pointer to an uint8 so I need a byte by byte conversion and there is a size input as well (no of bytes) and the inputs are all hex values,Please help me find whats wrong with my code.

Output was 0 always

uint8 ReferenceNumber[8] = {0x30,0x40,0x60,0x50,0x80,0x60,0x75,0x95};
HexToAscii(&ReferenceNumber[0], output, 8); 

static void HexToAscii(uint8* input, uint8 *output, uint8 size)//No of bytes
{
    uint8 i, temp;

    for(i=1; i<=size; i++)
    {
        temp = (*(input)) >> (4*(i-1));
        temp &= 0x0F;
        temp +='0';
        if (temp >= (10+'0'))
        {
            temp += ('A'-10-'0');
        }
        *(output+size-i) = temp;
    }
}
too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • 3
    What is the input, the actual result and the expected result? What did you find out by *debugging* your code? – Martin R Jul 21 '17 at 08:35
  • 1
    Do you want to convert from Hex to Char? – Rajeshkumar Jul 21 '17 at 08:53
  • 1
    And what output do you expect? – Jabberwocky Jul 21 '17 at 08:53
  • 1
    Hint: "0123456789ABCDEF" – Martin James Jul 21 '17 at 09:25
  • *(output+size-i) = temp; why are you swapping the ends? – old_timer Jul 21 '17 at 14:35
  • you have two (well three) choices compare with greater than 9 before you add to it then either add '0' (0x30) or add '0'+7 (0x37), or add the 0x30 then compare with 0x39 then add the 7 as needed (which is what you are attempting). That or use a look up table, not really much choice after that (switch statement I guess). And you are not converting from hex to ascii but from binary to ASCII hex or some other such verbage, bits in a computer are not hex they are binary. – old_timer Jul 21 '17 at 14:40
  • That is not a Hex to ASCII conversion, it is a conversion of 8 bit integers to ASCII hex representation. Just because the array is initialised with literal constant values using hex notation does not make the values hexadecimal, they are just integers - the function would be equally applicable if teh array were initialised with literal decimal, octal or character constants. – Clifford Jul 21 '17 at 20:07
  • The given input was just an example in my humble opinion, your assumption that it is always the input is not my fault. – Sivaramakrishna Shriraam Jul 24 '17 at 07:40

1 Answers1

2

The statement

temp = (*(input)) >> (4*(i-1));

could be rewritten as

uint8 x = *(input);
temp = x >> (4 * (i - 1));

or

temp = input[0] >> (4 * (i - 1));

And now you can see that you are actually shifting the same value for 0, 4, 8, 12,... bits to the right. And when shifting value to the right, you are padding 0's from the left side, therefore after 2 iterations of the loop, your temp variable is always 0.

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2^E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined. - ISO/IEC 9899:TC3, Section 6.5.7: Bitwise shift operators

You need to increment your input pointer. However in your code, you would need to repeat the code twice for every byte - for lower and upper 4 bits of the uint8.

This is how I would do it (replaced macro with inline function as pointed out by Olaf in the comment):

/*! \brief Convert nibble (lower 4 bits) to HEX value to avoid using standard libraries.
 */
static inline __attribute__((always_inline, const)) char
NibbleToHex(uint8_t nibble)  {
    return ((nibble <= 9) ? ('0' + nibble) : ('A' + nibble - 10));
}

static void HexToAscii(const uint8_t *input, char *output, uint8_t size) {
    while (size--) {
        *(output++) = NibbleToHex((*input) >> 4u);
        *(output++) = NibbleToHex((*input) & 0x0Fu);
        input++; /*< Move to the next byte. */
    }
}

uint8_t ReferenceNumber[8] = {0x30, 0x40, 0x60, 0x50, 0x80, 0x60, 0x75, 0x95};
HexToAscii(ReferenceNumber, output, sizeof(ReferenceNumber) / sizeof(ReferenceNumber[0])); 

Note: output must always the double the size of the input data (assuming that the size variable equals the length of the input data).

Bojan P.
  • 942
  • 1
  • 10
  • 21
  • excellent didnt see that coming!, i still wonder why i got a -1 for asking this though, input[0] is not the same as input?.. may be thats where my understanding went wrong! – Sivaramakrishna Shriraam Jul 21 '17 at 12:13
  • I do not know why you got a -1. In your case, `input` is a pointer on a variable of type `uint8` somewhere in the memory. You get the actual value located on that address by dereferencing the pointer with `*input`, which is equal to `input[0]`. Because you know that this pointer points to the multiple successive values (array), you can access following addresses. `*input == input[0]`, `*(input + 1) == input[1]`, `*(input + 123) == input[123]`,... I used manual incrementation of the pointer instead of indexing to remove the need for additional counter variable. – Bojan P. Jul 21 '17 at 12:28
  • yes i understand that *input is the same as input[0], but i think input and &input[0] should be the same, i missed the & in my first comment – Sivaramakrishna Shriraam Jul 21 '17 at 12:57
  • I see. You are correct - in this case, as in most cases, `input` and `&input[0]` are the same, I prefer `input` as it is less typing / clearer. However, be careful when using this with `sizeof` operator, as explained [in this answer](https://stackoverflow.com/a/41329292/5616255) and more thoroughly in [this answer](https://stackoverflow.com/a/4608421/5616255). However I just tested that in C and C++ 89/11/14 and both cases mentioned in the first linked answer gave the same, correct result. – Bojan P. Jul 21 '17 at 19:02
  • I think most of the time `input` form is used, as also seen in examples on SEI CERT page (which is good to check out), [EXP09-C. Use sizeof to determine the size of a type or variable](https://www.securecoding.cert.org/confluence/display/CINT/EXP09-C.+Use+sizeof+to+determine+the+size+of+a+type+or+variable). And speaking of `sizeof`, be careful to [ARR01-C. Do not apply the sizeof operator to a pointer when taking the size of an array](https://www.securecoding.cert.org/confluence/display/CINT/ARR01-C.+Do+not+apply+the+sizeof+operator+to+a+pointer+when+taking+the+size+of+an+array). – Bojan P. Jul 21 '17 at 19:08
  • Never use a macro where a function will do as well! – too honest for this site Jul 22 '17 at 04:05
  • @Olaf thank you for your remark. I just copied that piece of code from my older firmware and didn't think of that good programming practice. I edited the answer taking your remark into account. – Bojan P. Jul 22 '17 at 10:46