# Converting Char Array with hex values into 32-bit integer

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

1. ### Martin KleinerGuest

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

2. ### Nate EldredgeGuest

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

3. ### Martin AmbuhlGuest

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
4. ### Ben BacarisseGuest

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
5. ### CBFalconerGuest

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>

CBFalconer, Feb 11, 2009
6. ### RichardGuest

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
7. ### Nate EldredgeGuest

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
8. ### BoonGuest

Boon, Feb 11, 2009
9. ### Spiros BousbourasGuest

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;

char ninebytes[8];

Spiros Bousbouras, Feb 11, 2009
10. ### Spiros BousbourasGuest

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

Spiros Bousbouras, Feb 11, 2009
11. ### Spiros BousbourasGuest

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
12. ### Nate EldredgeGuest

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
13. ### CBFalconerGuest

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.

<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://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>