Anyone mind reviewing my code?

Discussion in 'C Programming' started by Mantorok Redgormor, Oct 2, 2003.

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

    int main(void)
    {
    unsigned int mask;
    int a = -1;
    mask = 1u << (CHAR_BIT * sizeof mask - 1);


    while(mask) {
    putchar(a & mask ? '1' : '0');
    mask>>=1u;
    }

    putchar('\n');

    return 0;
    }

    I was wanting to display the underlying representation
    of signed and unsigned integers. I don't think I am
    invoking undefined behavior but if I am, could someone
    point it out?

    Also, I can only use integer types with bitwise AND
    And this is a convenient way of testing against
    a mask. So how would one determine the bits
    set in a float or double type to display the
    underlying representation in binary?

    I thought about using the examples from a
    previously similar question I asked.
    Where the examples given displayed the bytes in hex
    I was thinking maybe I could display each individual
    byte by displaying those bytes in binary consecutively.
    But maybe there is a more clever way?
    Mantorok Redgormor, Oct 2, 2003
    #1
    1. Advertising

  2. On Thu, 2 Oct 2003, Mantorok Redgormor wrote:
    >
    > #include <stdio.h>
    > #include <limits.h>
    >
    > int main(void)
    > {
    > unsigned int mask;
    > int a = -1;
    > mask = 1u << (CHAR_BIT * sizeof mask - 1);


    Undefined behavior if 'unsigned int' has any
    padding bits, I think. At best, it's
    implementation-defined behavior.

    I believe

    mask = ~0u ^ (~0u >> 1)

    is guaranteed correct, although I could be
    mistaken. In general, this kind of bit-twiddling
    is highly representation-specific, since who
    in their right minds would write bit-twiddling
    code like this that *needed* to run on two different
    architectures?

    > while(mask) {
    > putchar(a & mask ? '1' : '0');
    > mask>>=1u;
    > }


    It would be even more portable to forget the bit
    twiddling entirely, and use a recursive approach:

    void print_bits(unsigned int x)
    {
    if (x != 0) print_bits(x/2);
    printf("%d", x&1);
    }


    print_bits(a);

    Exercise: Modify the above function to take an argument
    saying how many bits to print in all.

    > putchar('\n');
    >
    > return 0;
    > }



    > Also, I can only use integer types with bitwise AND
    > And this is a convenient way of testing against
    > a mask. So how would one determine the bits
    > set in a float or double type to display the
    > underlying representation in binary?


    Examine it as an array of 'unsigned char':

    double real = 3.141593;
    unsigned char *representation = (unsigned char *)&real;
    ...

    > I thought about using the examples from a
    > previously similar question I asked.
    > Where the examples given displayed the bytes in hex
    > I was thinking maybe I could display each individual
    > byte by displaying those bytes in binary consecutively.
    > But maybe there is a more clever way?


    Nope. :)

    -Arthur
    Arthur J. O'Dwyer, Oct 2, 2003
    #2
    1. Advertising

  3. "Arthur J. O'Dwyer" <> wrote in message news:<>...
    > On Thu, 2 Oct 2003, Mantorok Redgormor wrote:
    > >
    > > #include <stdio.h>
    > > #include <limits.h>
    > >
    > > int main(void)
    > > {
    > > unsigned int mask;
    > > int a = -1;
    > > mask = 1u << (CHAR_BIT * sizeof mask - 1);

    >
    > Undefined behavior if 'unsigned int' has any
    > padding bits, I think.


    Correct.

    > At best, it's implementation-defined behavior.
    >
    > I believe
    >
    > mask = ~0u ^ (~0u >> 1)


    I'm partial to...

    mask = -1u/2+1;

    >
    > is guaranteed correct, although I could be
    > mistaken. In general, this kind of bit-twiddling
    > is highly representation-specific,


    How many variant representations for unsigned types do you think there
    are? As far as the value bits are concerned, there is only one, 'pure
    binary'.

    > since who
    > in their right minds would write bit-twiddling
    > code like this that *needed* to run on two different
    > architectures?


    People implementing portable encryption or coding theory algorithms
    for one.

    But, dumping bit-sets in most to least-significant order is not that
    uncommon, or at least, I wouldn't have thought so.

    --
    Peter
    Peter Nilsson, Oct 3, 2003
    #3
  4. Mantorok Redgormor

    pete Guest

    Mantorok Redgormor wrote:

    > mask>>=1u;


    That letter 'u' there doesn't help.
    It doesn't hurt, but it doesn't help.

    --
    pete
    pete, Oct 3, 2003
    #4
  5. On Thu, 2 Oct 2003, Peter Nilsson wrote:
    >
    > "Arthur J. O'Dwyer" <> wrote...
    > > On Thu, 2 Oct 2003, Mantorok Redgormor wrote:
    > > >
    > > > mask = 1u << (CHAR_BIT * sizeof mask - 1);


    [Something else...]

    > > is guaranteed correct, although I could be
    > > mistaken. In general, this kind of bit-twiddling
    > > is highly representation-specific,

    >
    > How many variant representations for unsigned types do you think there
    > are? As far as the value bits are concerned, there is only one, 'pure
    > binary'.


    True. I had forgotten for a moment we were talking unsigned.
    However, the numbers of value bits and padding bits are still
    part of the implementation-defined representation.

    > > since who
    > > in their right minds would write bit-twiddling
    > > code like this that *needed* to run on two different
    > > architectures?

    >
    > People implementing portable encryption or coding theory algorithms
    > for one.


    While you may have a point, I think far more encryption schemes
    will *assume* 32-bit 'int' or 8-bit 'char', and work with those.
    Also, real code does not resort to weird bit-twiddling hacks to
    produce values like 0x80000000; you'd simply write that value,
    if that's what you meant. Or parameterize your coding algorithm
    to specify the width of the data type being coded.

    > But, dumping bit-sets in most to least-significant order is not that
    > uncommon, or at least, I wouldn't have thought so.


    True. That's why I gave the _portable_, recursive,
    non-bit-twiddling solution.

    -Arthur
    Arthur J. O'Dwyer, Oct 3, 2003
    #5
  6. On Thu, 2 Oct 2003 17:59:05 -0400 (EDT), "Arthur J. O'Dwyer"
    <> wrote:

    >
    > On Thu, 2 Oct 2003, Mantorok Redgormor wrote:

    <unsnip>
    > I was wanting to display the underlying representation
    > of signed and unsigned integers. I don't think I am
    > invoking undefined behavior but if I am, could someone
    > point it out?

    </>
    Note that none of these really display the underlying representation.
    Where they work at all they display the value bits of the unsigned
    value, which are (by requirement) much though possibly not all of the
    representation; or of the signed value converted to unsigned, which
    need not be so, although on two's-complement systems, the overwhelming
    majority by far today, they are.

    > >
    > > #include <stdio.h>
    > > #include <limits.h>
    > >
    > > int main(void)
    > > {
    > > unsigned int mask;
    > > int a = -1;
    > > mask = 1u << (CHAR_BIT * sizeof mask - 1);

    >
    > Undefined behavior if 'unsigned int' has any
    > padding bits, I think. At best, it's
    > implementation-defined behavior.
    >

    Not undefined. Shifts, like all other arithmetic operations, on
    unsigned (integer) types, are well-defined. In this case, if there
    are padding bits, which is i-d, the computed value will be reduced
    modulo (UINT_MAX+1) to zero, which is useless.

    > I believe
    >
    > mask = ~0u ^ (~0u >> 1)
    >
    > is guaranteed correct, although I could be
    > mistaken. In general, this kind of bit-twiddling
    > is highly representation-specific, since who
    > in their right minds would write bit-twiddling
    > code like this that *needed* to run on two different
    > architectures?
    >

    If you really did look at the representation, that is one type,
    perhaps the only type, of bit twiddling where you would have a real
    need to run on different platforms.

    > > while(mask) {
    > > putchar(a & mask ? '1' : '0');
    > > mask>>=1u;
    > > }

    >
    > It would be even more portable to forget the bit
    > twiddling entirely, and use a recursive approach:
    >
    > void print_bits(unsigned int x)
    > {
    > if (x != 0) print_bits(x/2);
    > printf("%d", x&1);
    > }
    >

    Or x%2 to avoid the bitwise operators altogether and be symmetric with
    /, although for unsigned types and a power of two any decent compiler
    on any non-brain-damaged platform will still implement as bit ops.

    And more direct and probably more efficient, putchar( x%2 +'0').

    <snip>
    > > Also, I can only use integer types with bitwise AND
    > > And this is a convenient way of testing against
    > > a mask. So how would one determine the bits
    > > set in a float or double type to display the
    > > underlying representation in binary?

    >
    > Examine it as an array of 'unsigned char':
    >
    > double real = 3.141593;
    > unsigned char *representation = (unsigned char *)&real;
    > ...
    >

    Right.

    - David.Thompson1 at worldnet.att.net
    Dave Thompson, Oct 6, 2003
    #6
  7. "Dave Thompson" <> wrote in message
    news:...
    > On Thu, 2 Oct 2003 17:59:05 -0400 (EDT), "Arthur J. O'Dwyer"
    > <> wrote:
    > > > unsigned int mask;
    > > > mask = 1u << (CHAR_BIT * sizeof mask - 1);

    > >
    > > Undefined behavior if 'unsigned int' has any
    > > padding bits, I think. At best, it's
    > > implementation-defined behavior.
    > >

    > Not undefined. Shifts, like all other arithmetic operations, on
    > unsigned (integer) types, are well-defined. In this case, if there
    > are padding bits, which is i-d, the computed value will be reduced
    > modulo (UINT_MAX+1) to zero, which is useless.


    Sorry Dave, you missed the first semantic paragraph...

    Bitwise shift operators
    ...
    The integral promotions are performed on each of the operands. The
    type of the result is that of the promoted left operand. If the value
    of the right operand is negative or is greater than or equal to the
    width in bits of the promoted left operand, the behavior is undefined.

    Note the term 'width' is defined earlier as sign + value bits.

    --
    Peter
    Peter Nilsson, Oct 6, 2003
    #7
  8. On Mon, 6 Oct 2003 17:37:22 +1000, "Peter Nilsson" <>
    wrote:

    > "Dave Thompson" <> wrote in message
    > news:...

    <snip>
    > > > > mask = 1u << (CHAR_BIT * sizeof mask - 1);

    <snip>
    > > Not undefined. <snip>


    > Sorry Dave, you missed the first semantic paragraph... <snip>


    Argh! I didn't miss it, I just forgot it. Sorry.

    - David.Thompson1 at worldnet.att.net
    Dave Thompson, Oct 20, 2003
    #8
    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. Lloyd Sheen
    Replies:
    8
    Views:
    381
    William LaMartin
    Nov 19, 2003
  2. Greg Hurlman
    Replies:
    5
    Views:
    1,923
    Greg Hurlman
    Dec 4, 2003
  3. Ashe Sjedic
    Replies:
    15
    Views:
    501
    Phillip Windell
    Feb 6, 2006
  4. Airy R Bean

    Re: Mind.Forth to C code?

    Airy R Bean, Aug 2, 2003, in forum: C Programming
    Replies:
    5
    Views:
    483
    Airy R Bean
    Aug 5, 2003
  5. JeanDean

    Tool for reviewing c++ code ?

    JeanDean, May 8, 2007, in forum: C++
    Replies:
    3
    Views:
    351
    JeanDean
    May 9, 2007
Loading...

Share This Page