0

I have a character array (an ethernet address like aa:bb:cc:dd:ee:ff) that I need to parse up into an unsigned char[6]. I'm using strtok to get each pair of characters, and I need to cast them into an unsigned char, but nothing I'm doing is working.

I've tried (assume c is a char* of length 2):

unsigned char t = (unsigned char)c;  // gives "loses precision" error

unsigned char* t = (unsigned char*)c;
unsigned char t1 = t[0];                  // gives the wrong value

unsigned char t;
strcpy((char*)t, c);      // gives the wrong value
strncpy((char*)t, c, sizeof(char)*2) // gives the wrong value
xdumaine
  • 10,096
  • 6
  • 62
  • 103
  • How is `c` defined? There is also a mistake in your `strncpy` code. – Sebastian Apr 21 '12 at 17:44
  • 2
    Have you tried [`strtoul(c, NULL, 16)`](http://www.cplusplus.com/reference/clibrary/cstdlib/strtoul/)? It will probably give you the "loses precision" warning, but will produce an unsigned integer (with the value of `0xAA` for the first token, etc). – DCoder Apr 21 '12 at 17:47
  • 1
    None of the code you've tried includes any form of "conversion". And a conversion is necessary here, since your source data is ASCII hexadecimal digits, and your desired result is a numeric value. – Ben Voigt Apr 21 '12 at 18:00
  • @BenVoigt That's my question. I know I'm not doing it correctly, I'm asking how. – xdumaine Apr 21 '12 at 18:15
  • @DCoder that works, actually. It doesn't produce that warning, either. – xdumaine Apr 21 '12 at 18:23

2 Answers2

0

Assuming that your input string is a hex string containing at most two hexadecimal numbers, i. e. FF you can use std::stringstream to do the conversion:

int n;

std::stringstream ss;
ss << std::hex << c;
ss >> n;

unsigned char x = (unsigned char)n;

You'll have to ensure, that c really is not bigger than FF.

EDIT: Changed the above code to read the value into an int first and then cast it to unsigned char. When reading directly into a char it's reading characters only without any conversion.

Sebastian
  • 8,046
  • 2
  • 34
  • 58
  • `std::hex` won't affect insertion of a string. Did you mean `ss >> std::hex >> n;`? I don't think that works either :( – Ben Voigt Apr 21 '12 at 18:01
  • Hm, just found another reference at SO: [C++ convert hex string to signed integer](http://stackoverflow.com/questions/1070497/c-convert-hex-string-to-signed-integer) which proposes the same as I do. – Sebastian Apr 21 '12 at 18:03
  • @BenVoigt I've tested this again and it works, but the variable for `ss >> n` must be an integer (made an edit for explanation). – Sebastian Apr 21 '12 at 18:11
0

The compiler sees what you are doing as casting a 32/64-bit pointer to an 8-bit number. Casting fundamental types is not going to interpret the contents of strings for you.

Think about it: how would it know what you specifically want to do? How does it know it's hex notation!

You're trying to convert strings containing hexadecimal values into numbers. That's a conversion you can't do by just casting fundamental types. Take a look at the answer to this question for a suggestion. Or, since you're in C++ you can use streams which I think are a little better. Example:

#include <sstream>
#include <iostream>
#include "stdio.h"

int main(int argc, char* argv[])
{
    char *addr[] = { "aa", "bb", "cc", "dd", "ee", "ff" };
    unsigned char binaddr[6];
    for(size_t i = 0; i < 6; ++i)
    {
        size_t word_result;
        std::istringstream addr_stream(addr[i]);
        addr_stream >> std::hex >> word_result;
        binaddr[i] = word_result;
    }
    printf("%x:%x:%x:%x:%x:%x\n", binaddr[0], binaddr[1], binaddr[2], binaddr[3], binaddr[4], binaddr[5]);
    return 0;

}
Community
  • 1
  • 1
smocking
  • 3,689
  • 18
  • 22