convert a char[4] (binary) to an unsigned long

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Vincent

    #16
    Re: convert a char[4] (binary) to an unsigned long

    Thanks for this suggestion. It works! Somewhere else in my script, I
    have to convert an unsigned long to a char[4]. I tried to use memcpy to
    create a LongtoChararr function, but i failed. I'm not very familiar
    with memcpy. Can you help me again?


    Hans wrote:[color=blue]
    > Vincent skrev:
    >[color=green]
    > > Hi all,
    > >
    > > I want to convert a char[4] (binary) to an unsigned long. How can I do
    > > this?
    > >
    > > Thanks,
    > > Vincent[/color]
    >
    > Use memcpy:
    >
    > unsigned long ChararrToLong(c onst char * const src)
    > {
    > unsigned long dest;
    > memcpy(&dest, src, sizeof(dest));
    > return dest;
    > }
    >
    >
    > This may be what you want or not. If you depend on the chars being put
    > in a specific order into the unsigned long, you might want to do some
    > byte-swapping while copying.[/color]

    Comment

    • Old Wolf

      #17
      Re: convert a char[4] (binary) to an unsigned long

      Tobias Blomkvist wrote:[color=blue]
      > Jack Klein sade:[color=green][color=darkred]
      >>>
      >>>assert(sizeo f(long) == 4);[/color]
      >>
      >> This doesn't actually solve the problem. And what happens if
      >> sizeof(long) is 8, which it is on some 64 bit platforms?[/color]
      >
      > It fails.
      >[color=green]
      >>[color=darkred]
      >>>char b[4] = {0x01,0x02,0x03 ,0x04};
      >>>unsigned long a = 0;
      >>>a |= (b[0] << 24);[/color]
      >>
      >>
      >> The problem here is that b[0] is promoted to either int or unsigned
      >> int before it is shifted. There are still a large number of platforms
      >> where long has 32 bits but int has only 16. Shifting by 24 on such a
      >> platform is undefined behavior, and will almost certainly give the
      >> wrong results.[/color]
      >
      > True. An
      > assert(sizeof(i nt) == 4);
      > would secure the code.[/color]

      Actually it wouldn't, eg. (8-bit signed char):
      char b[4] = { 0x01, 0x02, 0x03, 0x99 };

      Then 0x01020300 | 0x99 will become 0x01020300 | 0xFFFFFF99
      which is not the desired result. You have to make the
      chars unsigned before you apply bit operations to them.

      Comment

      • John Ratliff

        #18
        Re: convert a char[4] (binary) to an unsigned long

        Vincent wrote:[color=blue]
        > Thanks for this suggestion. It works! Somewhere else in my script, I
        > have to convert an unsigned long to a char[4]. I tried to use memcpy to
        > create a LongtoChararr function, but i failed. I'm not very familiar
        > with memcpy. Can you help me again?
        >[/color]

        If byte order is not essential, you can do reinterpret_cas t again.

        unsigned long ul = 0xFEDCBA98;
        char *ptr = reinterpret_cas t<char *>(&ul);

        Depending upon endianness, you will end up with one of these:
        ptr[] = {0xFE, 0xDC, 0xBA, 0x98}; // big endian machine
        ptr[] = {0x98, 0xBA, 0xDC, 0xFE}; // little endian machine

        Note if an unsigned long is not 4 bytes on the platform you're using,
        you will end up with a different sized array.

        If you really want to use memcpy,

        unsigned long ul = 0xFEDCBA98;
        char ptr[sizeof(unsigned long)];

        memcpy(ptr, &ul, sizeof(unsigned long));

        --John Ratliff

        Comment

        • Richard Herring

          #19
          Re: convert a char[4] (binary) to an unsigned long

          In message <1123512057.574 256.147910@f14g 2000cwb.googleg roups.com>,
          ThosRTanner <ttanner2@bloom berg.net> writes[color=blue]
          >&x points to a number of bytes which contain (on a big endian machine,
          >LSB is at highest byte address) 0, 0, ... , 1, and (on a little endian
          >machine, LSB is at lowest byte address) 1, 0, ... 0
          >
          >Interpreting the pointer as a char * and getting the byte pointed to
          >will return the contents of the lowest addressed byte of the word,
          >which will be 0 for big endian machines and 1 for little endian
          >machines.
          >
          >Optimising out the code is presumably a result of gcc recognising that
          >particular pattern - it would be rather dangerous if you were cross
          >compiling![/color]

          It's rather dangerous anyway if your target platform has
          sizeof(int)==si zeof(char).

          --
          Richard Herring

          Comment

          • Earl Purple

            #20
            Re: convert a char[4] (binary) to an unsigned long


            Vincent wrote:[color=blue]
            > Hi all,
            >
            > I want to convert a char[4] (binary) to an unsigned long. How can I do
            > this?[/color]

            My suggestion is to:
            - always use big-endian regardless of platform
            - use something like this:

            const size_t CHAR_BITS = 8; // or whatever it is on your system

            unsigned long makeLong( const char* data )
            {
            unsigned long result = 0;
            for ( int i=0; i<4; ++i )
            {
            result <<= CHAR_BITS;
            result |= data[i];
            }
            }

            that will work whenever sizeof(long) >= 4 or there are sufficient
            trailing 0 bytes that overflow does not occur.

            Comment

            Working...