Converting Char Array with hex values into 32-bit integer

Discussion in 'C Programming' started by Martin Kleiner, Feb 10, 2009.

  1. Hi

    I have an 8 byte array of hex characters, e.g.
    ['c','5','3','1','0','6','5','9'] and I wanna convert this
    to an unsigned int, so that unsigned int i = 0xc5310659. I wonder if
    in C there is an very easy way to do that?

    One cumbersome way to do that would be:

    unsigned int arrToInt = 0;

    for(i=0; i<8; i++) {
    arrToInt =(arrToInt<<8) | toIntVal(charBuffer);
    }

    int toIntVal(char c)
    {
    int value = 0;

    switch (c)
    {
    case '0':
    value = 0;
    break;
    case '1':
    value = 1;
    break;
    ....
    default:

    return val;
    }

    has someone an easier idea?

    Thanks!
     
    Martin Kleiner, Feb 10, 2009
    #1
    1. Advertising

  2. Martin Kleiner <> writes:

    > Hi
    >
    > I have an 8 byte array of hex characters, e.g.
    > ['c','5','3','1','0','6','5','9'] and I wanna convert this
    > to an unsigned int, so that unsigned int i = 0xc5310659. I wonder if
    > in C there is an very easy way to do that?


    You could add a terminating nul and use the standard `strtoul'
    function.

    char charBuffer[8] = { 'c','5','3','1','0','6','5','9' };
    char tmpbuf[9];
    char *q;
    unsigned long result;

    memcpy(tmpbuf, charBuffer, 8);
    tmpbuf[8] = '\0';
    result = strtoul(tmpbuf, &q, 16);
    if (q != &tmpbuf[8])
    fprintf(stderr, "Didn't convert 8 characters\n");
     
    Nate Eldredge, Feb 10, 2009
    #2
    1. Advertising

  3. Martin Kleiner wrote:
    > Hi
    >
    > I have an 8 byte array of hex characters, e.g.
    > ['c','5','3','1','0','6','5','9'] and I wanna convert this
    > to an unsigned int, so that unsigned int i = 0xc5310659. I wonder if
    > in C there is an very easy way to do that?


    The easy way is to have your 8 chars put into a string:

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    #include <stddef.h>

    int main(void)
    {
    /* note that the buffer is, as specifed 8 chars longs, so it is not a
    string. Were this declared with buff[], the trailing '\0' would
    have been supplied, and strtoul would do. */
    char buff[8] = "c5310659";
    /* note that the target is an unsigned long. An unsigned int, as the
    OP used, is allowed to have a maximum of 65535 (0xFFFF) so is
    inappropriate */
    unsigned long target;
    char cvt[] = "0123456789abcdef";
    /* a 9-byte buffer for another approach */
    char ninebytes[8];
    size_t i;
    char *p;
    ptrdiff_t j;
    _Bool crap = 0;

    /* approach 1 */
    for (i = 0, target = 0; i < 8; i++) {
    p = strchr(cvt, tolower(buff));

    if (!p) {
    crap = 1;
    printf("The character '%c' is not appropriate.\n", buff);
    break;
    }
    j = p - cvt;
    target = (target << 4) + j;
    }
    if (crap)
    printf
    ("warning, I stopped converting after the above error
    message\n");
    printf("Approach 1:\n"
    "The value of \"c5310569\" appears to be %lu (%#lx"
    " %#lo)\n\n",
    target, target, target);

    /* approach 2 */
    /* make a string */
    memcpy(ninebytes, buff, 8);
    ninebytes[8] = 0;
    target = strtoul(ninebytes, &p, 16);
    if (*p) {
    printf("There is an unconverted part of \"%s\" remaining,\n"
    "namely \"%s\"\n", buff, p);
    }
    printf("Approach 2:\n"
    "The value of \"c5310569\" appears to be %lu (%#lx"
    " %#lo)\n\n",
    target, target, target);


    return 0;
    }

    Approach 1:
    The value of "c5310569" appears to be 3308324441 (0xc5310659 030514203131)

    Approach 2:
    The value of "c5310569" appears to be 3308324441 (0xc5310659 030514203131)
     
    Martin Ambuhl, Feb 10, 2009
    #3
  4. Martin Kleiner <> writes:

    > I have an 8 byte array of hex characters, e.g.
    > ['c','5','3','1','0','6','5','9'] and I wanna convert this
    > to an unsigned int, so that unsigned int i = 0xc5310659. I wonder if
    > in C there is an very easy way to do that?


    Yes:

    char hex[8] = {'c','5','3','1','0','6','5','9'};
    unsigned int n;
    if (sscanf(hex, "%8x", &n) == 1)
    /* OK, use the number */

    This is one of the few places where a member of the *scanf family wins
    over the strto* functions.

    --
    Ben.
     
    Ben Bacarisse, Feb 11, 2009
    #4
  5. Martin Kleiner

    CBFalconer Guest

    Ben Bacarisse wrote:
    > Martin Kleiner <> writes:
    >
    >> I have an 8 byte array of hex characters, e.g.
    >> ['c','5','3','1','0','6','5','9'] and I wanna convert this
    >> to an unsigned int, so that unsigned int i = 0xc5310659. I
    >> wonder if in C there is an very easy way to do that?

    >
    > Yes:
    >
    > char hex[8] = {'c','5','3','1','0','6','5','9'};
    > unsigned int n;
    > if (sscanf(hex, "%8x", &n) == 1)
    > /* OK, use the number */
    >
    > This is one of the few places where a member of the *scanf
    > family wins over the strto* functions.


    Assuming int is a 32 bit quantity. Simpler to use long

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
     
    CBFalconer, Feb 11, 2009
    #5
  6. Martin Kleiner

    Richard Guest

    CBFalconer <> writes:

    > Ben Bacarisse wrote:
    >> Martin Kleiner <> writes:
    >>
    >>> I have an 8 byte array of hex characters, e.g.
    >>> ['c','5','3','1','0','6','5','9'] and I wanna convert this
    >>> to an unsigned int, so that unsigned int i = 0xc5310659. I
    >>> wonder if in C there is an very easy way to do that?

    >>
    >> Yes:
    >>
    >> char hex[8] = {'c','5','3','1','0','6','5','9'};
    >> unsigned int n;
    >> if (sscanf(hex, "%8x", &n) == 1)
    >> /* OK, use the number */
    >>
    >> This is one of the few places where a member of the *scanf
    >> family wins over the strto* functions.

    >
    > Assuming int is a 32 bit quantity. Simpler to use long


    Actually does someone have a pointer (or reference ...) to a good
    summary of C min/max values with explanations.
     
    Richard, Feb 11, 2009
    #6
  7. Richard <> writes:

    > CBFalconer <> writes:
    >
    >> Ben Bacarisse wrote:
    >>> Martin Kleiner <> writes:
    >>>
    >>>> I have an 8 byte array of hex characters, e.g.
    >>>> ['c','5','3','1','0','6','5','9'] and I wanna convert this
    >>>> to an unsigned int, so that unsigned int i = 0xc5310659. I
    >>>> wonder if in C there is an very easy way to do that?
    >>>
    >>> Yes:
    >>>
    >>> char hex[8] = {'c','5','3','1','0','6','5','9'};
    >>> unsigned int n;
    >>> if (sscanf(hex, "%8x", &n) == 1)
    >>> /* OK, use the number */
    >>>
    >>> This is one of the few places where a member of the *scanf
    >>> family wins over the strto* functions.

    >>
    >> Assuming int is a 32 bit quantity. Simpler to use long

    >
    > Actually does someone have a pointer (or reference ...) to a good
    > summary of C min/max values with explanations.


    Sections 1.1-1.4 of the C FAQ at http://c-faq.com/decl/index.html has
    some good info. Most relevant here is that `unsigned int' could be
    smaller than 32 bits. `unsigned long' is guaranteed to be at least that
    big, but could be bigger.

    <limits.h> contains macros giving the limits for the standard integer
    types.

    <stdint.h> has typedefs for integer types with various properties, and
    <inttypes.h> contains macros for using them with printf.

    If you have full C99 available to you, the best way to do this might be:

    #include <inttypes.h>
    #include <stdio.h>

    char hex[8] = {'c','5','3','1','0','6','5','9'};
    uint_fast32_t n;
    if (sscanf(hex, "%8" SCNxFAST32, &n) == 1)
    /* ok */

    uint_fast32_t is defined to be the most efficient integer type that's at
    least 32 bits, and SCNxFAST32 is the scanf specifier for that type in
    hex.
     
    Nate Eldredge, Feb 11, 2009
    #7
  8. Martin Kleiner

    Boon Guest

    Boon, Feb 11, 2009
    #8
  9. On 10 Feb, 18:32, Martin Ambuhl <> wrote:
    > Martin Kleiner wrote:
    > > Hi

    >
    > > I have an 8 byte array of hex characters, e.g.
    > > ['c','5','3','1','0','6','5','9'] and I wanna convert this
    > > to an unsigned int, so that unsigned int i = 0xc5310659. I wonder if
    > > in C there is an very easy way to do that?

    >
    > The easy way is to have your 8 chars put into a string:
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <ctype.h>
    > #include <string.h>
    > #include <stddef.h>
    >
    > int main(void)
    > {
    > /* note that the buffer is, as specifed 8 chars longs, so it is not a
    > string. Were this declared with buff[], the trailing '\0' would
    > have been supplied, and strtoul would do. */
    > char buff[8] = "c5310659";
    > /* note that the target is an unsigned long. An unsigned int, as the
    > OP used, is allowed to have a maximum of 65535 (0xFFFF) so is
    > inappropriate */
    > unsigned long target;
    > char cvt[] = "0123456789abcdef";
    > /* a 9-byte buffer for another approach */
    > char ninebytes[8];
    > size_t i;
    > char *p;
    > ptrdiff_t j;
    > _Bool crap = 0;
    >
    > /* approach 1 */
    > for (i = 0, target = 0; i < 8; i++) {
    > p = strchr(cvt, tolower(buff));
    >
    > if (!p) {
    > crap = 1;
    > printf("The character '%c' is not appropriate.\n", buff);
    > break;
    > }
    > j = p - cvt;
    > target = (target << 4) + j;
    > }
    > if (crap)
    > printf
    > ("warning, I stopped converting after the above error
    > message\n");
    > printf("Approach 1:\n"
    > "The value of \"c5310569\" appears to be %lu (%#lx"
    > " %#lo)\n\n",
    > target, target, target);
    >
    > /* approach 2 */
    > /* make a string */
    > memcpy(ninebytes, buff, 8);
    > ninebytes[8] = 0;


    Your definition was
    char ninebytes[8];
     
    Spiros Bousbouras, Feb 11, 2009
    #9
  10. On 10 Feb, 16:20, Martin Kleiner <> wrote:
    > Hi
    >
    > I have an 8 byte array of hex characters, e.g.
    > ['c','5','3','1','0','6','5','9'] and I wanna convert this
    > to an unsigned int, so that unsigned int i = 0xc5310659. I wonder if
    > in C there is an very easy way to do that?
    >
    > One cumbersome way to do that would be:
    >
    > unsigned int arrToInt = 0;
    >
    > for(i=0; i<8; i++) {
    > arrToInt =(arrToInt<<8) | toIntVal(charBuffer);
    >
    > }
    >
    > int toIntVal(char c)
    > {
    > int value = 0;
    >
    > switch (c)
    > {
    > case '0':
    > value = 0;
    > break;
    > case '1':
    > value = 1;
    > break;
    > ....
    > default:
    >
    > return val;
    >
    > }
    >
    > has someone an easier idea?


    Apart from the other suggestions, you can write
    int toIntVal(char c)
    {
    int value = 0;

    if ( '0' <= c && c <= '9' ) {
    value = c - '0' ;
    } else {
    switch (c)
    {
    case 'a':
    value = 10;
    break;
    case 'b':
    value = 11;
    break;
    ....
    default:
    /* Handle error */
    return val;

    }

    Personally I wouldn't use value at all but write
    multiple returns instead.
     
    Spiros Bousbouras, Feb 11, 2009
    #10
  11. On 10 Feb, 16:20, Martin Kleiner <> wrote:
    > Hi
    >
    > I have an 8 byte array of hex characters, e.g.
    > ['c','5','3','1','0','6','5','9'] and I wanna convert this
    > to an unsigned int, so that unsigned int i = 0xc5310659. I wonder if
    > in C there is an very easy way to do that?
    >
    > One cumbersome way to do that would be:
    >
    > unsigned int arrToInt = 0;
    >
    > for(i=0; i<8; i++) {
    > arrToInt =(arrToInt<<8) | toIntVal(charBuffer);
    >
    > }


    You need to shift by 4 bits at a time not 8.

    >
    > int toIntVal(char c)
    > {
    > int value = 0;
    >
    > switch (c)
    > {
    > case '0':
    > value = 0;
    > break;
    > case '1':
    > value = 1;
    > break;
    > ....
    > default:
    >
    > return val;
    >
    > }
    >
    > has someone an easier idea?
    >
    > Thanks!
     
    Spiros Bousbouras, Feb 11, 2009
    #11
  12. Spiros Bousbouras <> writes:

    > Apart from the other suggestions, you can write
    > int toIntVal(char c)
    > {
    > int value = 0;
    >
    > if ( '0' <= c && c <= '9' ) {
    > value = c - '0' ;


    I was about to complain that this might break in some strange character
    set, but I see that the standard (5.2.1 (3)) guarantees that the
    characters '0' through '9' occur contiguously and in order. That's
    useful knowledge.

    > } else {
    > switch (c)
    > {
    > case 'a':
    > value = 10;
    > break;
    > case 'b':
    > value = 11;
    > break;
    > ....
    > default:
    > /* Handle error */
    > return val;
    >
    > }


    However, there are no such guarantees for 'a' through 'f', so you are
    right to handle that separately.
     
    Nate Eldredge, Feb 11, 2009
    #12
  13. Martin Kleiner

    CBFalconer Guest

    Nate Eldredge wrote:
    > Richard <> writes:
    >

    .... snip ...
    >
    >> Actually does someone have a pointer (or reference ...) to a
    >> good summary of C min/max values with explanations.

    >
    > Sections 1.1-1.4 of the C FAQ at http://c-faq.com/decl/index.html
    > has some good info. Most relevant here is that `unsigned int'
    > could be smaller than 32 bits. `unsigned long' is guaranteed to
    > be at least that big, but could be bigger.
    >
    > <limits.h> contains macros giving the limits for the standard
    > integer types.


    The best references are <limits.h> and the C standard. References
    to C99 below are standard documents. n869_txt.bz2 is a bzipped
    text file of the last draft for C99.

    Some useful references about C:
    <http://www.ungerhu.com/jxh/clc.welcome.txt>
    <http://c-faq.com/> (C-faq)
    <http://benpfaff.org/writings/clc/off-topic.html>
    <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf> (C99)
    <http://cbfalconer.home.att.net/download/n869_txt.bz2> (pre-C99)
    <http://www.dinkumware.com/c99.aspx> (C-library}
    <http://gcc.gnu.org/onlinedocs/> (GNU docs)
    <http://clc-wiki.net/wiki/C_community:comp.lang.c:Introduction>
    <http://clc-wiki.net/wiki/Introduction_to_comp.lang.c>

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
     
    CBFalconer, Feb 12, 2009
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    10
    Views:
    6,223
    Neredbojias
    Aug 19, 2005
  2. silentlights

    converting char array to integer

    silentlights, Apr 15, 2004, in forum: C Programming
    Replies:
    22
    Views:
    91,973
    EventHelix.com
    Apr 19, 2004
  3. Bengt Richter
    Replies:
    6
    Views:
    474
    Juha Autero
    Aug 19, 2003
  4. lovecreatesbeauty
    Replies:
    1
    Views:
    1,065
    Ian Collins
    May 9, 2006
  5. Replies:
    5
    Views:
    231
    Tassilo v. Parseval
    Nov 22, 2005
Loading...

Share This Page