Question converting unsigned char [] to int

Discussion in 'C Programming' started by No Such Luck, Jun 17, 2005.

1. No Such LuckGuest

Hi all:

I have an unsigned char array (size 4):

unsigned char array[4];

array[0] = 0x00;
array[1] = 0x00;
array[2] = 0x02;
array[3] = 0xe7;

I would like to convert array[] to an integer.

0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743

Any help is appreciated.

No Such Luck, Jun 17, 2005

2. Guest

hi
first u need to understand the relationship between BCD representation.
like 3 is represented as 0111 and not 111. 4 will be considered as 0100
and not 100.so if u r given a number , say 0xe7, which means
11100111,shift it to right by 4.

int temp = array[3] >> 4;
which means
temp = 00001110 (= 0x0e)
int temp2 = array[3] << 4;
temp2 = 01110000 (0x70)
similarly u can split up all the elements by shifting and get the 4 bit
equivalents. convert them to get the exact BCD no.
hope that was of some help.

, Jun 17, 2005

3. MeGuest

> I have an unsigned char array (size 4):
>
> unsigned char array[4];
>
> array[0] = 0x00;
> array[1] = 0x00;
> array[2] = 0x02;
> array[3] = 0xe7;
>
> I would like to convert array[] to an integer.
>
> 0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743
>
> Any help is appreciated.

C doesn't guarantee that UCHAR_MAX <= UINT_MAX nor does it guarantee
that UINT_MAX is >= 0xFFFFFFFF. But here is something that will work if
you can guarantee the values in the array are <= 0xFF:

#define lengthof(a) (sizeof(a)/sizeof(a[0]))

const unsigned char array[4] = { 0, 0, 0x02, 0xe7 };
unsigned long ui = 0;
unsigned long mult = 1;

/*
it looks like you wanted big endian conversion. For little
endian, just index the array in the regular order
*/
for (unsigned i = 0; i < 4; ++i) {
ui += mult * array[lengthof(array)-1-i];
mult <<= 8;
}

assert(ui == 743);

Otherwise replace unsigned long and unsigned char with the uint32_t and
uint8_t types in stdint.h which is probably what you intended anyway.

Me, Jun 17, 2005
4. Guest

Me wrote:
> > I have an unsigned char array (size 4):
> >
> > unsigned char array[4];
> >
> > array[0] = 0x00;
> > array[1] = 0x00;
> > array[2] = 0x02;
> > array[3] = 0xe7;
> >
> > I would like to convert array[] to an integer.
> >
> > 0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743
> >
> > Any help is appreciated.

>
> C doesn't guarantee that UCHAR_MAX <= UINT_MAX nor does it guarantee
> that UINT_MAX is >= 0xFFFFFFFF. But here is something that will work if
> you can guarantee the values in the array are <= 0xFF:
>
> #define lengthof(a) (sizeof(a)/sizeof(a[0]))
>
> const unsigned char array[4] = { 0, 0, 0x02, 0xe7 };
> unsigned long ui = 0;
> unsigned long mult = 1;
>
> /*
> it looks like you wanted big endian conversion. For little
> endian, just index the array in the regular order
> */

<snip>

You don't need to do that for little endian. Whether it is little
or big endian, array[0] will always be 0,
array[1] will always be 0,
array[2] will always be 0x02, and
array[3] will always be 0xe7.

, Jun 17, 2005
5. Martin AmbuhlGuest

No Such Luck wrote:
> Hi all:
>
> I have an unsigned char array (size 4):
>
> unsigned char array[4];
>
> array[0] = 0x00;
> array[1] = 0x00;
> array[2] = 0x02;
> array[3] = 0xe7;
>
> I would like to convert array[] to an integer.
>
> 0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743

#include <stdio.h>
#include <limits.h>

int main(void)
{
unsigned i;
unsigned char a[4] = { 0x00, 0x00, 0x02, 0xe7 };

i = a[3] | (a[2] | (a[1] | a[0] << CHAR_BIT) << CHAR_BIT) <<
CHAR_BIT;
printf("i built up with left shifts & ors: %u\n", i);
return 0;
}

i built up with left shifts & ors: 743

Martin Ambuhl, Jun 17, 2005
6. Peter NilssonGuest

Me wrote:
> C doesn't guarantee that UCHAR_MAX <= UINT_MAX...

Yes, it does. [cf 6.2.5p8]

--
Peter

Peter Nilsson, Jun 17, 2005
7. MeGuest

> > C doesn't guarantee that UCHAR_MAX <= UINT_MAX...
>
> Yes, it does. [cf 6.2.5p8]

Yeah, that was really stupid of me. I meant to say that C doesn't
guarantee that pow(UCHAR_MAX+1,4)-1 <= UINT_MAX.

Me, Jun 17, 2005
8. Richard BosGuest

wrote:

[ If you _must_ use Google Broken Beta to post to Usenet, could you
on how to do so abound on Usenet, including in someone's sig here. ]

> first u need to understand the relationship between BCD representation.

BCD is irrelevant to the OP's problem; he's trying to concatenate bytes
into a (normal binary) integer, nothing more complicated.

> like 3 is represented as 0111 and not 111.

Where'd you get that? Even in BCD, 3 is represented by 0011, and 0111 is
7. That alone should've tipped you off that BCD is not the issue.

BTW, if you want to be taken seriously as a professional, learn to write
without script-kiddyisms such as "u" for you.

Richard

Richard Bos, Jun 17, 2005
9. peteGuest

Martin Ambuhl wrote:
>
> No Such Luck wrote:
> > Hi all:
> >
> > I have an unsigned char array (size 4):
> >
> > unsigned char array[4];
> >
> > array[0] = 0x00;
> > array[1] = 0x00;
> > array[2] = 0x02;
> > array[3] = 0xe7;
> >
> > I would like to convert array[] to an integer.
> >
> > 0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743

>
> #include <stdio.h>
> #include <limits.h>
>
> int main(void)
> {
> unsigned i;
> unsigned char a[4] = { 0x00, 0x00, 0x02, 0xe7 };
>
> i = a[3] | (a[2] | (a[1] | a[0] << CHAR_BIT) << CHAR_BIT) <<
> CHAR_BIT;
> printf("i built up with left shifts & ors: %u\n", i);
> return 0;
> }
>
> i built up with left shifts & ors: 743

If you're trying to make 743,
then it should be 8 instead of CHAR_BIT.

--
pete

pete, Jun 17, 2005
10. Lawrence KirbyGuest

On Thu, 16 Jun 2005 21:30:13 -0700, Me wrote:

>> I have an unsigned char array (size 4):
>>
>> unsigned char array[4];
>>
>> array[0] = 0x00;
>> array[1] = 0x00;
>> array[2] = 0x02;
>> array[3] = 0xe7;
>>
>> I would like to convert array[] to an integer.
>>
>> 0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743
>>
>> Any help is appreciated.

>
> C doesn't guarantee that UCHAR_MAX <= UINT_MAX nor does it guarantee

It does but that has been covered in other replies.

> that UINT_MAX is >= 0xFFFFFFFF. But here is something that will work if
> you can guarantee the values in the array are <= 0xFF:

Right.

> #define lengthof(a) (sizeof(a)/sizeof(a[0]))
>
> const unsigned char array[4] = { 0, 0, 0x02, 0xe7 };
> unsigned long ui = 0;
> unsigned long mult = 1;
>
> /*
> it looks like you wanted big endian conversion. For little
> endian, just index the array in the regular order
> */
> for (unsigned i = 0; i < 4; ++i) {
> ui += mult * array[lengthof(array)-1-i];
> mult <<= 8;
> }

Or perhaps

for (unsigned i = 0; i < lengthof(array); i++)
ui = (ui << 8) | array;

> assert(ui == 743);
>
> Otherwise replace unsigned long and unsigned char with the uint32_t and
> uint8_t types in stdint.h which is probably what you intended anyway.

You're much better off using unsigned long and unsigned char. They do the
job portably whereas uint32_t and uint8_t are non-=portable because an
implementation is only required to support them if it has a type with the
appropriate representation available. And of course they aren't supported
in C90 at all.

Lawrence

Lawrence Kirby, Jun 17, 2005
11. Martin AmbuhlGuest

pete wrote:
> Martin Ambuhl wrote:
>
>>No Such Luck wrote:
>>
>>>Hi all:
>>>
>>>I have an unsigned char array (size 4):
>>>
>>>unsigned char array[4];
>>>
>>>array[0] = 0x00;
>>>array[1] = 0x00;
>>>array[2] = 0x02;
>>>array[3] = 0xe7;
>>>
>>>I would like to convert array[] to an integer.
>>>
>>>0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743

>>
>>#include <stdio.h>
>>#include <limits.h>
>>
>>int main(void)
>>{
>> unsigned i;
>> unsigned char a[4] = { 0x00, 0x00, 0x02, 0xe7 };
>>
>> i = a[3] | (a[2] | (a[1] | a[0] << CHAR_BIT) << CHAR_BIT) <<
>> CHAR_BIT;
>> printf("i built up with left shifts & ors: %u\n", i);
>> return 0;
>>}
>>
>>i built up with left shifts & ors: 743

>
>
> If you're trying to make 743,
> then it should be 8 instead of CHAR_BIT.

But if you are trying to use whatever values an unsigned char holds,
it's CHAR_BIT. I never trust poster's arithmetic. It is "I would like
to conver array[] to an integer" to which I was responding, not the "=
743". The fact is, that "if you're trying to make 743" both 8 and
CHAR_BIT are irrelevant: just f*ing output 743 and screw where it came from.

Martin Ambuhl, Jun 17, 2005
12. Tim RentschGuest

Martin Ambuhl <> writes:

> No Such Luck wrote:
> > Hi all:
> >
> > I have an unsigned char array (size 4):
> >
> > unsigned char array[4];
> >
> > array[0] = 0x00;
> > array[1] = 0x00;
> > array[2] = 0x02;
> > array[3] = 0xe7;
> >
> > I would like to convert array[] to an integer.
> >
> > 0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743

>
> #include <stdio.h>
> #include <limits.h>
>
> int main(void)
> {
> unsigned i;
> unsigned char a[4] = { 0x00, 0x00, 0x02, 0xe7 };
>
> i = a[3] | (a[2] | (a[1] | a[0] << CHAR_BIT) << CHAR_BIT) <<
> CHAR_BIT;
> printf("i built up with left shifts & ors: %u\n", i);
> return 0;
> }
>
> i built up with left shifts & ors: 743

Although the code shown may work for this example, on different
values of the array elements it might result in undefined
behavior. The unsigned character values normally promote to
(signed) int, and shifting a signed value can produce UB.

Tim Rentsch, Jun 17, 2005
13. Old WolfGuest

Tim Rentsch wrote:
> Martin Ambuhl <> writes:
>> No Such Luck wrote:
>>>
>>> unsigned char array[4];
>>>
>>> array[0] = 0x00;
>>> array[1] = 0x00;
>>> array[2] = 0x02;
>>> array[3] = 0xe7;
>>>
>>> I would like to convert array[] to an integer.
>>> 0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743

>>
>> unsigned i;
>> unsigned char a[4] = { 0x00, 0x00, 0x02, 0xe7 };
>>
>> i = a[3] | (a[2] | (a[1] | a[0] << CHAR_BIT) << CHAR_BIT) <<
>> CHAR_BIT;

> Although the code shown may work for this example, on different
> values of the array elements it might result in undefined
> behavior. The unsigned character values normally promote to
> (signed) int, and shifting a signed value can produce UB.

If E1 is a signed int, then E1 << E2 only produces UB if E1
is negative or if E1 x 2^E2 is not representable by a signed int.

This situation would only arise if a[0] is 0x80 or greater
(assuming INT_MAX is 0x7FFFFFFF).
Martin Ambuhl's suggestion can be fixed by inserting a cast to
unsigned just after the first '|'.

Another option would be to replace "<< CHAR_BIT" with "* 256UL"
(the OP appears to want this, even if chars are not 8-bit).

Old Wolf, Jun 18, 2005
14. Tim RentschGuest

"Old Wolf" <> writes:

> Tim Rentsch wrote:
> > Martin Ambuhl <> writes:
> >> No Such Luck wrote:
> >>>
> >>> unsigned char array[4];
> >>>
> >>> array[0] = 0x00;
> >>> array[1] = 0x00;
> >>> array[2] = 0x02;
> >>> array[3] = 0xe7;
> >>>
> >>> I would like to convert array[] to an integer.
> >>> 0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743
> >>
> >> unsigned i;
> >> unsigned char a[4] = { 0x00, 0x00, 0x02, 0xe7 };
> >>
> >> i = a[3] | (a[2] | (a[1] | a[0] << CHAR_BIT) << CHAR_BIT) <<
> >> CHAR_BIT;

>
> > Although the code shown may work for this example, on different
> > values of the array elements it might result in undefined
> > behavior. The unsigned character values normally promote to
> > (signed) int, and shifting a signed value can produce UB.

>
> If E1 is a signed int, then E1 << E2 only produces UB if E1
> is negative or if E1 x 2^E2 is not representable by a signed int.
>
> This situation would only arise if a[0] is 0x80 or greater
> (assuming INT_MAX is 0x7FFFFFFF).

Yes, it produces undefined behavior only in some circumstances.
That's what I said.

> Martin Ambuhl's suggestion can be fixed by inserting a cast to
> unsigned just after the first '|'.

Yes, doing that will remove undefined behavior on some systems.

It's better though to write code that won't have undefined behavior
even on systems where INT_MAX < 0x7FFFFFFF; the code Lawrence Kirby
gave, for example.

Tim Rentsch, Jun 18, 2005
15. Peter Shaggy HaywoodGuest

Groovy hepcat was jivin' on 16 Jun 2005 21:20:41
-0700 in comp.lang.c.
Re: Question converting unsigned char [] to int's a cool scene! Dig
it!

>hi

Please provide context by quoting (the relevant portions of) the
post to which you are following up. Also, do not use d00dspeak-isms
think clearly before answering questions, so as not to post some utter
nonsense or red herring.

>first u need to understand the relationship between BCD representation.

Nonsense! What does BCD have to do with the price of fish? The OP
didn't mention BCD. He asked how to convert an array of unsigned char
to an integer.

>like 3 is represented as 0111 and not 111. 4 will be considered as 0100

The decimal number 3 is equal to the binary number 11. The binary
number 111 is equal to the decimal number 7. (The number of zeros
prepended to either number is irrelevant.)

>and not 100.so if u r given a number , say 0xe7, which means
>11100111,shift it to right by 4.

Huh? What on Earth are you talking about? Why would you do that?

>int temp = array[3] >> 4;
>which means
>temp = 00001110 (= 0x0e)
>int temp2 = array[3] << 4;
>temp2 = 01110000 (0x70)

And what is that in aid of? What possible benefit can be gained by
changing 0xe7 to 0x7e?

>similarly u can split up all the elements by shifting and get the 4 bit
>equivalents. convert them to get the exact BCD no.
>hope that was of some help.

I doubt very much that it was any help to anyone, I'm afraid.

--

Dig the even newer still, yet more improved, sig!

"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?

Peter Shaggy Haywood, Jun 19, 2005
16. Peter Shaggy HaywoodGuest

Groovy hepcat Me was jivin' on 16 Jun 2005 21:30:13 -0700 in
comp.lang.c.
Re: Question converting unsigned char [] to int's a cool scene! Dig
it!

>> I have an unsigned char array (size 4):
>>
>> unsigned char array[4];
>>
>> array[0] = 0x00;
>> array[1] = 0x00;
>> array[2] = 0x02;
>> array[3] = 0xe7;
>>
>> I would like to convert array[] to an integer.
>>
>> 0x00 0x00 0x02 0xe7 = 00000000 00000000 00000010 11100111 = 743
>>
>> Any help is appreciated.

>
>C doesn't guarantee that UCHAR_MAX <= UINT_MAX nor does it guarantee
>that UINT_MAX is >= 0xFFFFFFFF. But here is something that will work if
>you can guarantee the values in the array are <= 0xFF:
>
>#define lengthof(a) (sizeof(a)/sizeof(a[0]))
>
>const unsigned char array[4] = { 0, 0, 0x02, 0xe7 };
>unsigned long ui = 0;
>unsigned long mult = 1;
>
>/*
>it looks like you wanted big endian conversion. For little
>endian, just index the array in the regular order
>*/
>for (unsigned i = 0; i < 4; ++i) {
> ui += mult * array[lengthof(array)-1-i];
> mult <<= 8;
>}

Even better still (and tested):

#include <stdio.h>

int main(void)
{
unsigned char array[4] = {0, 0, 0x02, 0xe7};
unsigned long num;
int i;

num = 0;

for(i = 0; i < sizeof array; i++)
{
num <<= 8;
num |= array;
}

printf("num = %d\n", num);
return 0;
}

--

Dig the even newer still, yet more improved, sig!

"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?

Peter Shaggy Haywood, Jun 19, 2005
17. CBFalconerGuest

Peter Shaggy Haywood wrote:
>

.... snip ...
>
> Even better still (and tested):
>
> #include <stdio.h>
>
> int main(void)
> {
> unsigned char array[4] = {0, 0, 0x02, 0xe7};
> unsigned long num;
> int i;
>
> num = 0;
>
> for(i = 0; i < sizeof array; i++)
> {
> num <<= 8;
> num |= array;

num |= (array & 0xff);

> }
>
> printf("num = %d\n", num);
> return 0;
> }

<nit> Assuming you don't know the byte size or the array contents
in advance, the above change will insulate things and ensure you
use octets. Otherwise you would be well advised to replace 8 by
CHAR_BIT and #include <limits.h>. </nit>

--
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html

CBFalconer, Jun 19, 2005
18. Jean-Claude ArbautGuest

It's a perfect demonstration of KISS principle.
I won't forget this lesson

On 19/06/2005 23:09, CBFalconer wrote:

> Peter Shaggy Haywood wrote:
>>

> ... snip ...
>
>>
>> Even better still (and tested):
>>
>> #include <stdio.h>
>>
>> int main(void)
>> {
>> unsigned char array[4] = {0, 0, 0x02, 0xe7};
>> unsigned long num;
>> int i;
>>
>> num = 0;
>>
>> for(i = 0; i < sizeof array; i++)
>> {
>> num <<= 8;
>> num |= array;

>
> num |= (array & 0xff);
>
>> }
>>
>> printf("num = %d\n", num);
>> return 0;
>> }

>
> <nit> Assuming you don't know the byte size or the array contents
> in advance, the above change will insulate things and ensure you
> use octets. Otherwise you would be well advised to replace 8 by
> CHAR_BIT and #include <limits.h>. </nit>

Jean-Claude Arbaut, Jun 19, 2005
19. CBFalconerGuest

Jean-Claude Arbaut wrote:
> On 19/06/2005 23:09, CBFalconer wrote:
>> Peter Shaggy Haywood wrote:
>>>

>> ... snip ...
>>
>>>
>>> Even better still (and tested):
>>>
>>> #include <stdio.h>
>>>
>>> int main(void)
>>> {
>>> unsigned char array[4] = {0, 0, 0x02, 0xe7};
>>> unsigned long num;
>>> int i;
>>>
>>> num = 0;
>>> for(i = 0; i < sizeof array; i++) {
>>> num <<= 8;
>>> num |= array;

>>
>> num |= (array & 0xff);
>>
>>> }
>>>
>>> printf("num = %d\n", num);
>>> return 0;
>>> }

>>
>> <nit> Assuming you don't know the byte size or the array contents
>> in advance, the above change will insulate things and ensure you
>> use octets. Otherwise you would be well advised to replace 8 by
>> CHAR_BIT and #include <limits.h>. </nit>

>
> It's a perfect demonstration of KISS principle.
> I won't forget this lesson

Top-posting fixed. Even clearer, make it:

for (i = 0; i < sizeof array; i++)
num = num * 256 + (array & 0xff);

--
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html

CBFalconer, Jun 20, 2005