Question converting unsigned char [] to int

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

  1. No Such Luck

    No Such Luck Guest

    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
    #1
    1. Advertising

  2. No Such Luck

    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.

    badri
     
    , Jun 17, 2005
    #2
    1. Advertising

  3. No Such Luck

    Me Guest

    > 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
    #3
  4. No Such Luck

    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
    #4
  5. 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
    #5
  6. Me wrote:
    > C doesn't guarantee that UCHAR_MAX <= UINT_MAX...


    Yes, it does. [cf 6.2.5p8]

    --
    Peter
     
    Peter Nilsson, Jun 17, 2005
    #6
  7. No Such Luck

    Me Guest

    > > 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
    #7
  8. No Such Luck

    Richard Bos Guest

    wrote:

    [ If you _must_ use Google Broken Beta to post to Usenet, could you
    please ensure that you quote something when you reply? Instructions
    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
    #8
  9. No Such Luck

    pete Guest

    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
    #9
  10. 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
    #10
  11. 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
    #11
  12. No Such Luck

    Tim Rentsch Guest

    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
    #12
  13. No Such Luck

    Old Wolf Guest

    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
    #13
  14. No Such Luck

    Tim Rentsch Guest

    "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
    #14
  15. 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
    like "u" instead of "you" and "r" instead of "are". And please, please
    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!

    http://alphalink.com.au/~phaywood/
    "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
    #15
  16. 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!

    http://alphalink.com.au/~phaywood/
    "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
  17. No Such Luck

    CBFalconer Guest

    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>

    --
    Some informative links:
    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
    #17
  18. 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
    #18
  19. No Such Luck

    CBFalconer Guest

    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);

    --
    Some informative links:
    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
    #19
    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. Timo Freiberger
    Replies:
    3
    Views:
    954
    Bob Hairgrove
    Oct 30, 2004
  2. Hal Styli
    Replies:
    14
    Views:
    1,650
    Old Wolf
    Jan 20, 2004
  3. er
    Replies:
    6
    Views:
    492
    Andre Kostur
    Sep 14, 2007
  4. ciccio

    int*unsigned int = unsigned?

    ciccio, Jun 4, 2010, in forum: C++
    Replies:
    2
    Views:
    413
    Öö Tiib
    Jun 4, 2010
  5. pozz
    Replies:
    12
    Views:
    746
    Tim Rentsch
    Mar 20, 2011
Loading...

Share This Page