Converting Char Array with hex values into 32-bit integer

M

Martin Kleiner

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!
 
N

Nate Eldredge

Martin Kleiner said:
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");
 
M

Martin Ambuhl

Martin said:
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)
 
B

Ben Bacarisse

Martin Kleiner said:
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.
 
C

CBFalconer

Ben said:
Martin Kleiner said:
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
 
R

Richard

CBFalconer said:
Ben said:
Martin Kleiner said:
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.
 
N

Nate Eldredge

Richard said:
CBFalconer said:
Ben said:
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.
 
S

Spiros Bousbouras

Martin said:
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];
 
S

Spiros Bousbouras

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.
 
S

Spiros Bousbouras

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.
 
N

Nate Eldredge

Spiros Bousbouras said:
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.
 
C

CBFalconer

Nate said:
.... snip ...


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>
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top