bits and stuff

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

    #1

    bits and stuff

    #include <stdio.h>

    int main()
    {
    unsigned long num;
    unsigned int a = 10, b = 20, c = 30, d = 40;
    /* num = 0; */

    num |= a << 24;
    num |= b << 16;
    num |= c << 8;
    num |= d << 0;

    printf("a = %02.2x\nb = %02.2x\nc = %02.2x\nd = %02.2x\n", a, b, c, d);
    printf("num = %08.8x\n", num);

    return 0;
    }

    What I'm trying to do here is pack a, b, c, and d into num.

    It works if I set num = 0, but how come it's not working if I leave it out
    (like above)? I know that when num is declared, its memory contents is full
    of garbage, but I thought that by packing the ints into it would've
    overwritten all the garbage? (hope that makes sense)

    Thanks,
    Joe




  • Artie Gold

    #2
    Re: bits and stuff

    Joe Laughlin wrote:[color=blue]
    > #include <stdio.h>
    >
    > int main()
    > {
    > unsigned long num;
    > unsigned int a = 10, b = 20, c = 30, d = 40;
    > /* num = 0; */
    >
    > num |= a << 24;[/color]

    This is the same as writing:
    num = num | a << 24;

    i.e. you're doing a bitwise `or' of whatever was in `num' and `a'
    left-shifted 24 bits. See what the problem is?
    [color=blue]
    > num |= b << 16;
    > num |= c << 8;
    > num |= d << 0;
    >
    > printf("a = %02.2x\nb = %02.2x\nc = %02.2x\nd = %02.2x\n", a, b, c, d);
    > printf("num = %08.8x\n", num);
    >
    > return 0;
    > }
    >
    > What I'm trying to do here is pack a, b, c, and d into num.
    >
    > It works if I set num = 0, but how come it's not working if I leave it out
    > (like above)? I know that when num is declared, its memory contents is full
    > of garbage, but I thought that by packing the ints into it would've
    > overwritten all the garbage? (hope that makes sense)
    >[/color]
    See above.

    HTH,
    --ag


    --
    Artie Gold -- Austin, Texas

    "What they accuse you of -- is what they have planned."

    Comment

    • Mark McIntyre

      #3
      Re: bits and stuff

      On Fri, 11 Jun 2004 23:01:49 GMT, in comp.lang.c , "Joe Laughlin"
      <Joseph.V.Laugh lin@boeing.com> wrote:
      [color=blue]
      >#include <stdio.h>
      >
      >int main()
      >{
      > unsigned long num;[/color]

      this is an uninitialised variable. It contains garbage.
      [color=blue]
      > num |= a << 24;[/color]

      here you OR the bits of a with garbage.
      GIGO.
      [color=blue]
      >What I'm trying to do here is pack a, b, c, and d into num.[/color]

      This is not guaranteed to work at all - you're assuming that
      sizeof(long)==4 which need not be true.
      [color=blue]
      >I thought that by packing the ints into it would've
      >overwritten all the garbage? (hope that makes sense)[/color]

      You're ORing it with the garbage.

      --
      Mark McIntyre
      CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
      CLC readme: <http://www.angelfire.c om/ms3/bchambless0/welcome_to_clc. html>


      ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
      http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
      ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---


      ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
      http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
      ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---

      Comment

      • Jack Klein

        #4
        Re: bits and stuff

        On Sat, 12 Jun 2004 00:27:04 +0100, Mark McIntyre
        <markmcintyre@s pamcop.net> wrote in comp.lang.c:
        [color=blue]
        > On Fri, 11 Jun 2004 23:01:49 GMT, in comp.lang.c , "Joe Laughlin"
        > <Joseph.V.Laugh lin@boeing.com> wrote:
        >[color=green]
        > >#include <stdio.h>
        > >
        > >int main()
        > >{
        > > unsigned long num;[/color]
        >
        > this is an uninitialised variable. It contains garbage.
        >[color=green]
        > > num |= a << 24;[/color]
        >
        > here you OR the bits of a with garbage.
        > GIGO.
        >[color=green]
        > >What I'm trying to do here is pack a, b, c, and d into num.[/color]
        >
        > This is not guaranteed to work at all - you're assuming that
        > sizeof(long)==4 which need not be true.[/color]

        No he's not. He's assuming that unsigned long contains at least 32
        value bits, and that is guaranteed by the standard.

        On the compiler I used at work today, unsigned long has exactly 32
        value bits. And sizeof(unsigned long) is 2, not 4.
        [color=blue][color=green]
        > >I thought that by packing the ints into it would've
        > >overwritten all the garbage? (hope that makes sense)[/color]
        >
        > You're ORing it with the garbage.[/color]

        Well, that's true.

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

        • Jack Klein

          #5
          Re: bits and stuff

          On Fri, 11 Jun 2004 23:01:49 GMT, "Joe Laughlin"
          <Joseph.V.Laugh lin@boeing.com> wrote in comp.lang.c:

          In addition to what others have said, you're risking undefined
          behavior in ways they haven't pointed out.
          [color=blue]
          > #include <stdio.h>
          >
          > int main()
          > {
          > unsigned long num;
          > unsigned int a = 10, b = 20, c = 30, d = 40;
          > /* num = 0; */
          >
          > num |= a << 24;[/color]

          The C standard requires that signed and unsigned ints be able to
          represent a range of values that requires them to have at least 16
          bits. There are indeed implementations where an unsigned int has 16
          bits and no more, although this is no longer common in popular desk
          top systems. On such a system, shifting an unsigned int left by 24,
          or by 16 as below, generates undefined behavior.

          This should be written as:

          num = (unsigned long)a << 24;

          The first one only should be "=" rather than "|=".
          [color=blue]
          > num |= b << 16;[/color]

          This one also needs the cast to (unsigned long). The other two do
          not.
          [color=blue]
          > num |= c << 8;
          > num |= d << 0;
          >
          > printf("a = %02.2x\nb = %02.2x\nc = %02.2x\nd = %02.2x\n", a, b, c, d);
          > printf("num = %08.8x\n", num);
          >
          > return 0;
          > }
          >
          > What I'm trying to do here is pack a, b, c, and d into num.
          >
          > It works if I set num = 0, but how come it's not working if I leave it out
          > (like above)? I know that when num is declared, its memory contents is full
          > of garbage, but I thought that by packing the ints into it would've
          > overwritten all the garbage? (hope that makes sense)
          >
          > Thanks,
          > Joe[/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

          • CBFalconer

            #6
            Re: bits and stuff

            Mark McIntyre wrote:[color=blue]
            > <Joseph.V.Laugh lin@boeing.com> wrote:
            >[color=green]
            >> #include <stdio.h>
            >>
            >> int main()
            >> {
            >> unsigned long num;[/color]
            >
            > this is an uninitialised variable. It contains garbage.
            >[color=green]
            >> num |= a << 24;[/color]
            >
            > here you OR the bits of a with garbage.
            > GIGO.
            >[color=green]
            >> What I'm trying to do here is pack a, b, c, and d into num.[/color]
            >
            > This is not guaranteed to work at all - you're assuming that
            > sizeof(long)==4 which need not be true.
            >[color=green]
            >> I thought that by packing the ints into it would've
            >> overwritten all the garbage? (hope that makes sense)[/color]
            >
            > You're ORing it with the garbage.[/color]

            In addition, the "a << 24" expression above is an int expression.
            It is only converted to long for the addition to num, which is too
            late. If int happens to be 16 bits you have undefined behaviour.
            Thus that should be written as:

            ((unsigned long)a << 24)

            and similarly for the b value. Next you should worry about
            CHAR_BIT being larger than 8, and a,b,c,d potentially containing
            values larger than 255.

            --
            Chuck F (cbfalconer@yah oo.com) (cbfalconer@wor ldnet.att.net)
            Available for consulting/temporary embedded and systems.
            <http://cbfalconer.home .att.net> USE worldnet address!


            Comment

            • Stephen L.

              #7
              Re: bits and stuff

              Joe Laughlin wrote:[color=blue]
              >
              > #include <stdio.h>
              >
              > int main()
              > {
              > unsigned long num;
              > unsigned int a = 10, b = 20, c = 30, d = 40;
              > /* num = 0; */
              >
              > num |= a << 24;
              > num |= b << 16;
              > num |= c << 8;
              > num |= d << 0;
              >
              > printf("a = %02.2x\nb = %02.2x\nc = %02.2x\nd = %02.2x\n", a, b, c, d);
              > printf("num = %08.8x\n", num);
              >
              > return 0;
              > }
              >
              > What I'm trying to do here is pack a, b, c, and d into num.
              >
              > It works if I set num = 0, but how come it's not working if I leave it out
              > (like above)? I know that when num is declared, its memory contents is full
              > of garbage, but I thought that by packing the ints into it would've
              > overwritten all the garbage? (hope that makes sense)
              >
              > Thanks,
              > Joe[/color]

              Other posters pointed out the issues with
              the above.

              Have you thought about using a union (let the
              compiler do the work for you)?

              int
              main()
              {
              union {
              unsigned long n;
              unsigned char piece[ sizeof (unsigned long) ];
              } num;
              unsigned int a = 10, b = 20, c = 30, d = 40;

              num.piece[ 0 ] = a;
              num.piece[ 1 ] = b;
              num.piece[ 2 ] = c;
              num.piece[ 3 ] = d;

              printf("a = %2.2x\nb = %2.2x\nc = %2.2x\nd = %2.2x\n", a, b, c, d);
              printf("num = %8.8lx\n", num.n);

              return (0);
              }

              Of course, if your unsigned ints overflow what will fit
              in an unsigned char, you'll get unknown results...


              HTH,

              Stephen

              Comment

              • Chris Torek

                #8
                Re: bits and stuff

                >Joe Laughlin wrote:
                [code that uses left-shift and bitwise-OR to construct a 32-bit value
                from four eight-bit values, with a slight flaw]

                In article <news:40CAE948. 5931BC2E@cost-com.net>
                Stephen L. <sdlnospamar@co st-com.net> writes:[color=blue]
                >Other posters pointed out the issues with
                >the above.
                >
                >Have you thought about using a union (let the
                >compiler do the work for you)?[/color]

                This method has advantages and disadvantages. Often the
                disadvantages outweigh the advantages:
                [color=blue]
                > union {
                > unsigned long n;
                > unsigned char piece[ sizeof (unsigned long) ];
                > } num;
                >
                > num.piece[ 0 ] = a;[/color]
                [and so on]
                [color=blue]
                >Of course, if your unsigned ints overflow what will fit
                >in an unsigned char, you'll get unknown results...[/color]

                The disadvantage of using the union trick -- or, equivalently,
                using an "unsigned char *" to point to the individual C-bytes that
                make up an "unsigned long" -- is that you expose yourself to the
                implementation' s representation. In particular, on common
                implementations today, you now have to worry about:

                - sizeof(unsigned long) changing from 4 to 8
                - endianness

                The advantage of using the union trick is the same as the disadvantage:
                you expose yourself to the implementation' s representation. If
                that is what you *want* to do, go ahead and do it. On the other
                hand, if you just want to compose a predictable 32-bit value from
                four eight-bit values, the shift-and-bitwise-OR method will always
                work. The common concerns above (sizeof(unsigne d long) and
                endinanness) become entirely irrelevant.
                --
                In-Real-Life: Chris Torek, Wind River Systems
                Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
                email: forget about it http://web.torek.net/torek/index.html
                Reading email is like searching for food in the garbage, thanks to spammers.

                Comment

                • CBFalconer

                  #9
                  Re: bits and stuff

                  "Stephen L." wrote:[color=blue]
                  >[/color]
                  .... snip ...[color=blue]
                  >
                  > Have you thought about using a union (let the
                  > compiler do the work for you)?
                  >
                  > int
                  > main()
                  > {
                  > union {
                  > unsigned long n;
                  > unsigned char piece[ sizeof (unsigned long) ];
                  > } num;
                  > unsigned int a = 10, b = 20, c = 30, d = 40;[/color]

                  That approach is inherently unsafe, both for misuse of the union,
                  and for dependence on byte sex.

                  --
                  Chuck F (cbfalconer@yah oo.com) (cbfalconer@wor ldnet.att.net)
                  Available for consulting/temporary embedded and systems.
                  <http://cbfalconer.home .att.net> USE worldnet address!

                  Comment

                  • Michael Mair

                    #10
                    Re: bits and stuff

                    Hiho,


                    [union-for-bytewise-access][color=blue]
                    >
                    > That approach is inherently unsafe, both for misuse of the union,
                    > and for dependence on byte sex.[/color]

                    Mmmm, I know about the former but could you or someone else please
                    expand your answer concerning the latter? I am not even sure what
                    you mean by byte sex...
                    I quickly scanned the question list of the faq and did not find
                    one dealing with this. For accessing double bits/bytes/words/whatever,
                    I would rather look at the memory representation with the
                    help of pointers but I am not sure whether this is the only, let
                    alone the best way.


                    Cheers,
                    Michael

                    Comment

                    • Mark McIntyre

                      #11
                      Re: bits and stuff

                      On Fri, 11 Jun 2004 21:26:13 -0500, in comp.lang.c , Jack Klein
                      <jackklein@spam cop.net> wrote:
                      [color=blue]
                      >On Sat, 12 Jun 2004 00:27:04 +0100, Mark McIntyre
                      ><markmcintyre@ spamcop.net> wrote in comp.lang.c:
                      >[color=green]
                      >> On Fri, 11 Jun 2004 23:01:49 GMT, in comp.lang.c , "Joe Laughlin"
                      >> <Joseph.V.Laugh lin@boeing.com> wrote:
                      >>
                      >>[color=darkred]
                      >> >What I'm trying to do here is pack a, b, c, and d into num.[/color]
                      >>
                      >> This is not guaranteed to work at all - you're assuming that
                      >> sizeof(long)==4 which need not be true.[/color]
                      >
                      >No he's not. He's assuming that unsigned long contains at least 32
                      >value bits,[/color]

                      And that each of his unsigned ints has at most 8 relevant value bits. Is
                      that certain, on all implementations ?
                      [color=blue]
                      >and that is guaranteed by the standard.[/color]

                      You're right in that.
                      [color=blue]
                      >On the compiler I used at work today, unsigned long has exactly 32
                      >value bits. And sizeof(unsigned long) is 2, not 4.[/color]

                      I'd be interested to know if it has a comforming hosted implementation tho
                      :-)


                      --
                      Mark McIntyre
                      CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
                      CLC readme: <http://www.angelfire.c om/ms3/bchambless0/welcome_to_clc. html>


                      ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
                      http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
                      ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---


                      ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
                      http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
                      ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---

                      Comment

                      • Mark McIntyre

                        #12
                        Re: bits and stuff

                        On Sat, 12 Jun 2004 07:30:16 -0400, in comp.lang.c , "Stephen L."
                        <sdlnospamar@co st-com.net> wrote:
                        [color=blue]
                        >Joe Laughlin wrote:[color=green]
                        >>[/color]
                        >Have you thought about using a union (let the
                        >compiler do the work for you)?[/color]

                        snip example of packing a union and then unpacking it differently.
                        [color=blue]
                        >Of course, if your unsigned ints overflow what will fit
                        >in an unsigned char, you'll get unknown results...[/color]

                        But reading from a union by accessing a member other than that which you
                        wrote last is UB anyway. Its a common extension to place meaning on the
                        behaviour of course, but you can't rely on it.

                        --
                        Mark McIntyre
                        CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
                        CLC readme: <http://www.angelfire.c om/ms3/bchambless0/welcome_to_clc. html>


                        ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
                        http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
                        ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---


                        ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
                        http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
                        ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---

                        Comment

                        • Mark McIntyre

                          #13
                          Re: bits and stuff

                          On Sun, 13 Jun 2004 22:23:09 +0200, in comp.lang.c , Michael Mair
                          <mairRemove_for _mailinG@ians.u ni-stuttgart.de> wrote:
                          [color=blue]
                          >Hiho,
                          >
                          >
                          >[union-for-bytewise-access][color=green]
                          >>
                          >> That approach is inherently unsafe, both for misuse of the union,
                          >> and for dependence on byte sex.[/color]
                          >
                          >Mmmm, I know about the former but could you or someone else please
                          >expand your answer concerning the latter? I am not even sure what
                          >you mean by byte sex...[/color]

                          I think CBF means Endianness. See Chris Torek's post.

                          --
                          Mark McIntyre
                          CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
                          CLC readme: <http://www.angelfire.c om/ms3/bchambless0/welcome_to_clc. html>


                          ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
                          http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
                          ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---


                          ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
                          http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
                          ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---

                          Comment

                          • those who know me have no need of my name

                            #14
                            Re: bits and stuff

                            in comp.lang.c i read:
                            [color=blue]
                            >[union-for-bytewise-access][color=green]
                            >> That approach is inherently unsafe, both for misuse of the union,
                            >> and for dependence on byte sex.[/color]
                            >
                            >Mmmm, I know about the former but could you or someone else please
                            >expand your answer concerning the latter? I am not even sure what
                            >you mean by byte sex...[/color]

                            which end of the array of bytes is the least significant, i.e., is the
                            least significant byte [0] or [sizeof object - 1]? and those are not the
                            only possibilities if sizeof object is greater than 2, where [1] is another
                            though it's not common to see these days.

                            signed long value = 1;
                            unsigned char bytes[sizeof value];
                            memcpy(bytes, &value, sizeof value);
                            /* is bytes[0], bytes[1] or bytes[sizeof bytes - 1], or some other, the 1? */

                            today one tends to see 01 00 00 00 (little endian) or 00 00 00 01 (big
                            endian), which correspond to b[0] or b[sizeof b - 1] having the 1.

                            and that ignores padding, which is, again, unlikely these days but it is
                            allowed, and for all anyone knows it will reappear or you're program will
                            have to work on a dinosaur. if there is padding then it may be that none
                            of the bytes in my example will be a 1, or there may be more than one with
                            a non-zero value.

                            oh, and what if sizeof value is 1? are you thinking `how can such a thing
                            be'? in c it is possible if CHAR_BIT is 32 or larger, which is seen on
                            today's dsp's. in that case you aren't accessing octets, which is often
                            what people want to do with the sort of tricks discussed, rather you are
                            accessing the one, 32 bit, byte, hence [0] is all there is, but how you
                            serialize it's octets remains an issue.

                            all this makes working with internal representations a difficult and
                            tedious, though not insurmountable thing.

                            --
                            a signature

                            Comment

                            • CBFalconer

                              #15
                              Re: bits and stuff

                              Michael Mair wrote:[color=blue]
                              >
                              > [union-for-bytewise-access][color=green]
                              >>
                              >> That approach is inherently unsafe, both for misuse of the union,
                              >> and for dependence on byte sex.[/color]
                              >
                              > Mmmm, I know about the former but could you or someone else please
                              > expand your answer concerning the latter? I am not even sure what
                              > you mean by byte sex...[/color]

                              Also known as endianess. The order of octets within the
                              representation of an integer, or other item. I know of at least 3
                              fairly popular versions for 32 bit integers. The shift, mask, and
                              add method is independant of this.

                              --
                              Chuck F (cbfalconer@yah oo.com) (cbfalconer@wor ldnet.att.net)
                              Available for consulting/temporary embedded and systems.
                              <http://cbfalconer.home .att.net> USE worldnet address!


                              Comment

                              Working...