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

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

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

    Hi all,

    I want to convert a char[4] (binary) to an unsigned long. How can I do
    this?

    Thanks,
    Vincent

  • Tobias Blomkvist

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

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

    assert(sizeof(l ong) == 4);
    char b[4] = {0x01,0x02,0x03 ,0x04};
    unsigned long a = 0;
    a |= (b[0] << 24);
    a |= (b[1] << 16);
    a |= (b[2] << 8);
    a |= b[3];

    But if you have MSB in b[3] then you should reverse the order.
    Beware of big endian and little endian.

    Tobias
    --
    IMPORTANT: The contents of this email and attachments are confidential
    and may be subject to legal privilege and/or protected by copyright.
    Copying or communicating any part of it to others is prohibited and may
    be unlawful.

    Comment

    • John Ratliff

      #3
      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?
      >
      > Thanks,
      > Vincent
      >[/color]

      I don't think this is possible without knowing the endian-ness of the
      machine. Maybe someone will correct me.

      If the char[4] came from the machine, then you could probably do a
      reinterpret_cas t, but I'm almost positive it won't be portable.

      // assume this has your binary unsigned long
      extern char ul_bin[4];
      unsigned long ul = *reinterpret_ca st<unsigned long *>(ul_bin);

      --John Ratliff

      Comment

      • Vincent

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

        The program will have to work on MS Windows 2000. The char[4] is a set
        of characters, read from a file.

        I hope this will help you answering my question.

        Comment

        • Hans

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


          Vincent skrev:
          [color=blue]
          > 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.

          Comment

          • Tobias Blomkvist

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

            Vincent sade:[color=blue]
            > The program will have to work on MS Windows 2000. The char[4] is a set
            > of characters, read from a file.
            >
            > I hope this will help you answering my question.
            >[/color]

            Find out what format the long's are stored in, what endianness.

            long l = 0x04030201

            can be stored as

            Big endian: 0x04030201
            Little endian: 0x01020304

            Or any random order you desire in your file, but if you don't
            know the byte order, how will you be able to read them back correctly?



            Tobias
            --
            IMPORTANT: The contents of this email and attachments are confidential
            and may be subject to legal privilege and/or protected by copyright.
            Copying or communicating any part of it to others is prohibited and may
            be unlawful.

            Comment

            • John Ratliff

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

              Vincent wrote:[color=blue]
              > The program will have to work on MS Windows 2000. The char[4] is a set
              > of characters, read from a file.
              >
              > I hope this will help you answering my question.
              >[/color]

              It will only work if the char[4] read from Windows was created on a
              machine with endian-ness the same as Windows 2000 (little endian for
              x86) written in endian correct order.

              In other words, if you wrote an unsigned long created on a machine to a
              file, and then wanted to read that unsigned long from a char[4] byte
              array on the same machine, the reinterpret_cas t would work. If this file
              is created on some other machine, you can only know if it would work if
              you know the endian-ness of the machine which created the file.

              A question though, why are you reading an unsigned long into a char[4]
              array anyways? Why not read it directly into an unsigned long? Or, how
              does the unsigned long get written in the first place? Maybe you should
              consider writing it as a string instead and parsing the string back
              using strtoul() instead.

              --John Ratliff

              Comment

              • Jack Klein

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

                On Fri, 05 Aug 2005 12:25:38 +0200, Tobias Blomkvist <void@void.void >
                wrote in comp.lang.c++:
                [color=blue]
                > Vincent sade:[color=green]
                > > Hi all,
                > >
                > > I want to convert a char[4] (binary) to an unsigned long. How can I do
                > > this?
                > >
                > > Thanks,
                > > Vincent
                > >[/color]
                >
                > assert(sizeof(l ong) == 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=blue]
                > 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.

                Perhaps you think that the extra step of initializing 'a' to 0 and
                using |= forces b[0] to be promoted to unsigned long. It most
                certainly does not. b[0] is promoted to either int or unsigned int,
                the shift is performed and assuming there is no undefined behavior or
                the program continues regardless, the resulting unsigned int value is
                only then promoted to unsigned long.

                Should be:

                unsigned long a = ((unsigned long)b1 << 24);
                [color=blue]
                > a |= (b[1] << 16);[/color]

                Same cast here.
                [color=blue]
                > a |= (b[2] << 8);
                > a |= b[3];[/color]

                The last two do not need the cast. Except maybe platforms where
                unsigned char and int both have 16 bits, and the value in the unsigned
                char is greater than 255. And yes, there are platforms like this that
                actually have C++ compilers.
                [color=blue]
                > But if you have MSB in b[3] then you should reverse the order.
                > Beware of big endian and little endian.
                >
                > Tobias[/color]

                --
                Jack Klein
                Home: http://JK-Technology.Com
                FAQs for
                comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
                comp.lang.c++ http://www.parashift.com/c++-faq-lite/
                alt.comp.lang.l earn.c-c++

                Comment

                • Gianni Mariani

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

                  John Ratliff wrote:
                  [color=blue]
                  > I don't think this is possible without knowing the endian-ness of the
                  > machine. Maybe someone will correct me.[/color]

                  int x = 1;

                  endianness = * (char *) & x ? LITTLE_ENDIAN : BIG_ENDIAN;

                  Some compilers (GCC for sure) can optimize away code using this expression.

                  e.g.

                  int x = 1;
                  if ( * (char *) & x )
                  {
                  ... little endian code ...
                  ... optimized away when compiled for a little endian machine ...
                  } else
                  {
                  ... big endian code ...
                  ... optimized away when compiled for a big endian machine ...
                  }

                  Comment

                  • Gianni Mariani

                    #10
                    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]


                    See:



                    Comment

                    • Tobias Blomkvist

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

                      Jack Klein sade:[color=blue][color=green][color=darkred]
                      >>>[/color]
                      >>
                      >>assert(sizeof (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=blue]
                      >[color=green]
                      >>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=blue]
                      >
                      > The last two do not need the cast. Except maybe platforms where
                      > unsigned char and int both have 16 bits, and the value in the unsigned
                      > char is greater than 255. And yes, there are platforms like this that
                      > actually have C++ compilers.[/color]

                      On the other hand, writing code like this, you must be aware. Why do
                      you think I used assert?

                      Tobias
                      --
                      IMPORTANT: The contents of this email and attachments are confidential
                      and may be subject to legal privilege and/or protected by copyright.
                      Copying or communicating any part of it to others is prohibited and may
                      be unlawful.

                      Comment

                      • Fraser Ross

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

                        "Gianni Mariani"[color=blue]
                        > int x = 1;
                        >
                        > endianness = * (char *) & x ? LITTLE_ENDIAN : BIG_ENDIAN;[/color]

                        Can someone explain how this expression works? std::reverse is useful for
                        changing endiann type.

                        Fraser.


                        Comment

                        • Fraser Ross

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

                          "Fraser Ross"[color=blue]
                          > "Gianni Mariani"[color=green]
                          > > int x = 1;
                          > >
                          > > endianness = * (char *) & x ? LITTLE_ENDIAN : BIG_ENDIAN;[/color]
                          >
                          > Can someone explain how this expression works? std::reverse is useful for
                          > changing endiann type.
                          >
                          > Fraser.
                          >
                          >[/color]

                          I see it now. A static_cast would be more understandable. For a moment I
                          thought there was a use of a bit-wise operator.

                          Fraser.


                          Comment

                          • Fraser Ross

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


                            "Fraser Ross"[color=blue]
                            > I see it now. A static_cast would be more understandable.[/color]

                            No, reinterpret_cas t is required.

                            Fraser.


                            Comment

                            • ThosRTanner

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

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

                              Comment

                              Working...