reinterpret_cast - to interpret double as long

Discussion in 'C++' started by Suzanne Vogel, Jul 6, 2003.

  1. I'd like to convert a double to a binary representation. I can use the
    "&" bit operation with a bit mask to convert *non* float types to binary
    representations, but I can't use "&" on doubles.

    To get around this limitation on double, I'd like to keep the bits of
    the double the *same* but change its interpretation to long. I can use
    "&" on longs. I tried to use reinterpret_cast for this purpose, but it
    returned zero every time.

    double n1 = 32;
    long n2 = *(reinterpret_cast<long*>(&n)); // returns zero, for all n1

    *** How can I keep the bits of the double the *same* but change its
    interpretation to long? What am I doing wrong?

    Thanks,
    Suzanne
    Suzanne Vogel, Jul 6, 2003
    #1
    1. Advertising

  2. Do you want the bit pattern or the value???

    "Suzanne Vogel" <> wrote in message
    news:3f0858c5$...
    > I'd like to convert a double to a binary representation. I can use the
    > "&" bit operation with a bit mask to convert *non* float types to binary
    > representations, but I can't use "&" on doubles.
    >
    > To get around this limitation on double, I'd like to keep the bits of
    > the double the *same* but change its interpretation to long. I can use
    > "&" on longs. I tried to use reinterpret_cast for this purpose, but it
    > returned zero every time.
    >
    > double n1 = 32;
    > long n2 = *(reinterpret_cast<long*>(&n)); // returns zero, for all n1
    >
    > *** How can I keep the bits of the double the *same* but change its
    > interpretation to long? What am I doing wrong?
    >
    > Thanks,
    > Suzanne
    >
    Jesper Madsen, Jul 6, 2003
    #2
    1. Advertising

  3. "Suzanne Vogel" <> wrote...
    > I'd like to convert a double to a binary representation. I can use the
    > "&" bit operation with a bit mask to convert *non* float types to binary
    > representations, but I can't use "&" on doubles.
    >
    > To get around this limitation on double, I'd like to keep the bits of
    > the double the *same* but change its interpretation to long. I can use
    > "&" on longs. I tried to use reinterpret_cast for this purpose, but it
    > returned zero every time.
    >
    > double n1 = 32;
    > long n2 = *(reinterpret_cast<long*>(&n)); // returns zero, for all n1
    >
    > *** How can I keep the bits of the double the *same* but change its
    > interpretation to long? What am I doing wrong?


    On your platform 'double' is likely longer than 'long'. And
    your hardware is likely little-endian. '32' as a double has
    zero mantissa. That means that only the UPPER two bytes have
    some non-zero bits in them. The lower six bytes are all zeroes
    for any double that is a power of two. When you ask for the
    address of the double, you get the address of the lowest byte.
    Reinterpreting it as an address of a long gives you four lower
    bytes. They have no bits set in them.

    You need at least two longs to see the bit pattern in a double
    on your platform. Try doing this (non-portable!):

    double d1 = 32;
    unsigned long *plong = reinterpret_cast<unsigned long*>(&d1);
    unsigned long n1 = plong[0], n2 = plong[1];

    and see what you get in n1 and n2. (I used unsigned long because
    they are better for bit patterns)

    Once again: this code has nothing to do with standard C++. It
    produces _undefined_behaviour_. Whatever it happens to do on
    your platform is not what it should do on any other platform
    (or even with a different version of the same compiler).

    Victor
    Victor Bazarov, Jul 6, 2003
    #3
  4. "Suzanne Vogel" <> wrote in message
    news:3f0858c5$...
    > I'd like to convert a double to a binary representation. I can use the
    > "&" bit operation with a bit mask to convert *non* float types to binary
    > representations, but I can't use "&" on doubles.
    >
    > To get around this limitation on double, I'd like to keep the bits of
    > the double the *same* but change its interpretation to long. I can use
    > "&" on longs. I tried to use reinterpret_cast for this purpose, but it
    > returned zero every time.
    >
    > double n1 = 32;
    > long n2 = *(reinterpret_cast<long*>(&n)); // returns zero, for all n1
    >
    > *** How can I keep the bits of the double the *same* but change its
    > interpretation to long? What am I doing wrong?


    Its pretty unlikely that long is the same size as double. I would guess that
    you are only seeing half your double, and that half is all zero.

    You could try this

    double n1 = 32;
    long n2 = *(reinterpret_cast<long*>(&n));
    long n3 = *(reinterpret_cast<long*>(&n) + 1);

    But a more reliable method would be to use a union

    union
    {
    double d;
    char c[sizeof(double)];
    } conv;

    conv.d = 32;
    // print out double in hex
    for (int i =0; i < sizeof(double); ++i
    cout << hex << setfill('0') << setw(2) << conv.c;


    >
    > Thanks,
    > Suzanne
    >


    john
    John Harrison, Jul 6, 2003
    #4
  5. The bit pattern.

    Jesper Madsen wrote:
    > Do you want the bit pattern or the value???
    Suzanne Vogel, Jul 6, 2003
    #5
  6. "Suzanne Vogel" <> wrote in message
    news:3f0858c5$...
    > I'd like to convert a double to a binary representation.



    It already has one. Do you mean you want to see the 1s and 0s?



    > I can use the
    > "&" bit operation with a bit mask to convert *non* float types to binary
    > representations, but I can't use "&" on doubles.
    >
    > To get around this limitation on double, I'd like to keep the bits of
    > the double the *same* but change its interpretation to long. I can use
    > "&" on longs. I tried to use reinterpret_cast for this purpose, but it
    > returned zero every time.
    >
    > double n1 = 32;
    > long n2 = *(reinterpret_cast<long*>(&n)); // returns zero, for all n1
    >
    > *** How can I keep the bits of the double the *same* but change its
    > interpretation to long? What am I doing wrong?



    Better tel us exactly what you want to do, rather than describe it.




    --
    Ioannis

    * Programming pages: http://www.noicys.freeurl.com
    * Alternative URL 1: http://run.to/noicys
    * Alternative URL 2: http://www.noicys.cjb.net
    Ioannis Vranos, Jul 6, 2003
    #6
  7. Thanks, all. Victor's solution worked. Indeed, a double on my machine is
    twice as big as a long.

    Yes, what I meant by my question was that I wanted to see the
    machine-dependent 0's and 1's that a double consisted of.

    I encapsulated the conversion in a class. Instead of assuming that a
    double is twice as big (or whatever) as a long on *everyone*'s machine,
    I use sizeof() to test.

    FINDING (perhaps of interest to the "-0 vs. 0" folks):
    For doubles, my machine uses signed-bit representation (i.e., a 1-bit to
    represent the sign), with the exception that it represents 0 and -0 the
    same way. The compiler actually compiles -0 as 0, which I can see by
    setting a breakpoint at "double x = -0" and noting that the disassembly
    code does the assignment by XOR-ing a register with itself to the give
    value 0 (*not* -0).

    (All the question marks below are because I can't delete my array
    without getting an exception. But that's kind of irrelevant to this thread.)

    /******************************************************************************
    * Class to reinterpret the bits of 'value' of type 'From' to type 'To'.
    * i.e., Keep the bits the same, but reinterpret the value.
    * This gives the system-dependent binary representation.
    ******************************************************************************/
    template<class To, class From>
    class ReinterpretCast {
    private:
    std::string representation;
    public:
    ReinterpretCast() {
    // no-op
    }
    ReinterpretCast(From value) {
    int sizeOfOutput = (sizeof(From)>sizeof(To)) ?
    (sizeof(From)/sizeof(To)) : 1;
    To* buffer = new To[sizeOfOutput];
    buffer = reinterpret_cast<To*>(&value);
    for (int i=0; i<sizeOfOutput; i++) {
    representation += toBinary<To>(buffer); // toBinary() is
    a function I wrote, which gives the machine-dependent 0's and 1's
    }
    //delete[] buffer; // ??????????????????????????????????????????
    }
    ReinterpretCast(const ReinterpretCast<class To, class From>& rhs) {
    representation = rhs.representation;
    }
    ~ReinterpretCast() {
    // no-op
    }
    std::string getRepresentation() const {
    return representation;
    }
    int operator==(const ReinterpretCast& rhs) const {
    return typeid(this)==typeid(&rhs) &&
    representation==rhs.representation;
    }
    };

    Then, to see the binary representation of double(32.0), I can do:
    std::cout << "double: " << ReinterpretCast<long, double>
    (double(32.0)).getRepresentation() << "\n";

    The whole mess is posted here:
    http://www.cs.unc.edu/~vogel/playpen/c /std/BaseAndBitReps/Main.cpp
    I'll spare you by not pasting any more of the code into this message.

    Suzanne

    > On your platform 'double' is likely longer than 'long'. And
    > your hardware is likely little-endian. '32' as a double has
    > zero mantissa. That means that only the UPPER two bytes have
    > some non-zero bits in them. The lower six bytes are all zeroes
    > for any double that is a power of two. When you ask for the
    > address of the double, you get the address of the lowest byte.
    > Reinterpreting it as an address of a long gives you four lower
    > bytes. They have no bits set in them.
    >
    > You need at least two longs to see the bit pattern in a double
    > on your platform. Try doing this (non-portable!):
    >
    > double d1 = 32;
    > unsigned long *plong = reinterpret_cast<unsigned long*>(&d1);
    > unsigned long n1 = plong[0], n2 = plong[1];
    >
    > and see what you get in n1 and n2. (I used unsigned long because
    > they are better for bit patterns)
    >
    > Once again: this code has nothing to do with standard C++. It
    > produces _undefined_behaviour_. Whatever it happens to do on
    > your platform is not what it should do on any other platform
    > (or even with a different version of the same compiler).
    >
    > Victor
    >
    >
    Suzanne Vogel, Jul 6, 2003
    #7
  8. "Suzanne Vogel" <> wrote...
    > Thanks, all. Victor's solution worked. Indeed, a double on my machine is
    > twice as big as a long.
    >
    > Yes, what I meant by my question was that I wanted to see the
    > machine-dependent 0's and 1's that a double consisted of.
    >
    > I encapsulated the conversion in a class. Instead of assuming that a
    > double is twice as big (or whatever) as a long on *everyone*'s machine,
    > I use sizeof() to test.
    >
    > FINDING (perhaps of interest to the "-0 vs. 0" folks):
    > For doubles, my machine uses signed-bit representation (i.e., a 1-bit to
    > represent the sign), with the exception that it represents 0 and -0 the
    > same way. The compiler actually compiles -0 as 0, which I can see by
    > setting a breakpoint at "double x = -0" and noting that the disassembly
    > code does the assignment by XOR-ing a register with itself to the give
    > value 0 (*not* -0).


    The compiler will NOT create code for -0 when compiling "-0"
    expression. -0 is an integer expression resulting in (int)0.
    What you need is to somehow flip that sign bit in the double
    value. Not guaranteed to be printable, anyway.

    On your system:

    double a = 0.0;
    *(reinterpret_cast<char*>(&a) + sizeof(a) - 1) ^= 0x80;
    // here 'a' is -0 but you cannot see it.

    > (All the question marks below are because I can't delete my array
    > without getting an exception. But that's kind of irrelevant to this

    thread.)
    > [...]
    > ReinterpretCast(From value) {
    > int sizeOfOutput = (sizeof(From)>sizeof(To)) ?
    > (sizeof(From)/sizeof(To)) : 1;
    > To* buffer = new To[sizeOfOutput];


    Why do you think you need to allocate anything here?

    > buffer = reinterpret_cast<To*>(&value);


    So, you allocate 'buffer' and then immediately change its value
    to point to something else. How do you expect to 'delete' it?
    It loses the value you obtained from 'new' here. A memory leak.

    > for (int i=0; i<sizeOfOutput; i++) {
    > representation += toBinary<To>(buffer); // toBinary() is
    > a function I wrote, which gives the machine-dependent 0's and 1's
    > }
    > //delete[] buffer; // ??????????????????????????????????????????


    Drop the 'new', you don't need it.

    I decided not to comment on the rest of it.

    Victor
    Victor Bazarov, Jul 6, 2003
    #8
  9. > Why do you think you need to allocate anything here?
    >
    >> buffer = reinterpret_cast<To*>(&value);

    >
    > So, you allocate 'buffer' and then immediately change its value
    > to point to something else. How do you expect to 'delete' it?


    Oops, I see that now.

    > I decided not to comment on the rest of it.


    However, the comment "I decided not to comment on the rest of it" made
    me suspect that my code sucked, so I've been refactoring it. Even if
    that was not the intended meaning, well, my code still sucked. I split
    up the files, got rid of a couple of functions, renamed a couple of things.

    > Victor
    >

    Thanks,
    Suzanne
    Suzanne Vogel, Jul 6, 2003
    #9
  10. "Suzanne Vogel" <> wrote in message
    news:...
    > > Why do you think you need to allocate anything here?
    > >
    > >> buffer = reinterpret_cast<To*>(&value);

    > >
    > > So, you allocate 'buffer' and then immediately change its value
    > > to point to something else. How do you expect to 'delete' it?

    >
    > Oops, I see that now.
    >
    > > I decided not to comment on the rest of it.

    >
    > However, the comment "I decided not to comment on the rest of it" made
    > me suspect that my code sucked, so I've been refactoring it. Even if
    > that was not the intended meaning, well, my code still sucked. I split
    > up the files, got rid of a couple of functions, renamed a couple of

    things.


    Why don't you deal with the double as a sequence of unsigned chars?




    --
    Ioannis

    * Programming pages: http://www.noicys.freeurl.com
    * Alternative URL 1: http://run.to/noicys
    * Alternative URL 2: http://www.noicys.cjb.net
    Ioannis Vranos, Jul 6, 2003
    #10
  11. Victor or someone,

    *** What does this line do? i.e., How does it translate into the format
    "[l-value] = [something]"?
    *(reinterpret_cast<char*>(&a) + sizeof(a) - 1) ^= 0x80;

    I thought it would do the following, but it doesn't:
    a = (*(reinterpret_cast<char*>(&minusZero) + sizeof(minusZero)-1) ^
    0x80);

    *** Why are you using "sizeof(a)-1"?

    I'm sorry, but this particular syntax and bit formatting is foreign to
    me. Thanks.

    Suzanne

    Victor Bazarov wrote:
    > The compiler will NOT create code for -0 when compiling "-0"
    > expression. -0 is an integer expression resulting in (int)0.
    > What you need is to somehow flip that sign bit in the double
    > value. Not guaranteed to be printable, anyway.
    >
    > On your system:
    >
    > double a = 0.0;
    > *(reinterpret_cast<char*>(&a) + sizeof(a) - 1) ^= 0x80;
    > // here 'a' is -0 but you cannot see it.
    >
    Suzanne Vogel, Jul 7, 2003
    #11
  12. "Suzanne Vogel" <> wrote...
    > Victor or someone,
    >
    > *** What does this line do? i.e., How does it translate into the format
    > "[l-value] = [something]"?
    > *(reinterpret_cast<char*>(&a) + sizeof(a) - 1) ^= 0x80;


    If P is a char*, then P + N is also a char*. *(P + N) is a char&
    (a reference to a char).

    > I thought it would do the following, but it doesn't:
    > a = (*(reinterpret_cast<char*>(&minusZero) + sizeof(minusZero)-1) ^
    > 0x80);
    >
    > *** Why are you using "sizeof(a)-1"?


    That's the _last_, the most significant, byte of 'a' (if your
    system is little-endian). What else would I use?

    > I'm sorry, but this particular syntax and bit formatting is foreign to
    > me. Thanks.


    OK, you could write

    char *pa = reinterpret_cast<char*>(&a) + sizeof(a) - 1; // address
    char &ra = *pa; // get a reference from the address
    ra = ra ^ 0x80; // flip the bit in the char using the reference.

    I just wrote it in one statement. (Of course this works only on
    a system that is little-endian and has 8-bit chars)

    I supposed you need to read about compound assignment operators
    as well. Have you ever seen a += b? If yes, why a ^= b looks
    so foreign to you? If not, well, open your textbook...

    >
    > Suzanne
    >
    > Victor Bazarov wrote:
    > > The compiler will NOT create code for -0 when compiling "-0"
    > > expression. -0 is an integer expression resulting in (int)0.
    > > What you need is to somehow flip that sign bit in the double
    > > value. Not guaranteed to be printable, anyway.
    > >
    > > On your system:
    > >
    > > double a = 0.0;
    > > *(reinterpret_cast<char*>(&a) + sizeof(a) - 1) ^= 0x80;
    > > // here 'a' is -0 but you cannot see it.
    > >

    >
    Victor Bazarov, Jul 7, 2003
    #12
  13. Suzanne Vogel

    Sean Guest

    "Suzanne Vogel" <> wrote in message
    news:3f08d4ce$...
    > Victor or someone,
    >
    > *** What does this line do? i.e., How does it translate into the format
    > "[l-value] = [something]"?
    > *(reinterpret_cast<char*>(&a) + sizeof(a) - 1) ^= 0x80;
    >


    Hi Suzanne,

    Sometimes it's easier to understand if you break it
    down into multiple statements instead:

    char* tmp1 = reinterpret_cast<char *>(&a);
    tmp1 = tmp1 + sizeof(a) - 1;
    (*tmp1) ^= 0x80;

    Here's a small program to play around with this:

    #include<iostream>
    using std::cout;
    using std::hex;
    using std::endl;

    int main()
    {
    cout << hex; // Set output to hex formatting

    {
    unsigned int a = 0xa5a5a5a5;
    *(reinterpret_cast<char*>(&a) + sizeof(a) - 1) ^= 0x80;
    cout << a << endl; // Prints: 25a5a5a5
    }

    {
    unsigned int a = 0xa5a5a5a5;
    char* tmp1 = reinterpret_cast<char *>(&a);
    tmp1 = tmp1 + sizeof(a) - 1;
    *tmp1 ^= 0x80;
    cout << a << endl; // Prints: 25a5a5a5
    }

    }

    HTH,
    Sean


    > I thought it would do the following, but it doesn't:
    > a = (*(reinterpret_cast<char*>(&minusZero) + sizeof(minusZero)-1) ^
    > 0x80);
    >
    > *** Why are you using "sizeof(a)-1"?
    >
    > I'm sorry, but this particular syntax and bit formatting is foreign to
    > me. Thanks.
    >
    > Suzanne
    Sean, Jul 7, 2003
    #13
  14. Thanks for the additional comments.

    Victor Bazarov wrote:
    >>*** What does this line do? i.e., How does it translate into the format
    >>"[l-value] = [something]"?
    >> *(reinterpret_cast<char*>(&a) + sizeof(a) - 1) ^= 0x80;

    >
    > If P is a char*, then P + N is also a char*. *(P + N) is a char&
    > (a reference to a char).


    Yes... But here it seems we have *(char* + int), not *(char* + int*):
    *(reinterpret_cast<char*>(&a) + sizeof(a)-1) ^= 0x80;
    If I could see how we *do* have *(char* + int*), then I could understand
    why adding a mere value of "sizeof(a) - 1" accomplishes a bit shift (see
    below).

    ** Why does it accomplish a bit shift??????

    >
    >>I thought it would do the following, but it doesn't:
    >> a = (*(reinterpret_cast<char*>(&a) + sizeof(a)-1) ^ 0x80);
    >>
    >>*** Why are you using "sizeof(a)-1"?

    >
    > That's the _last_, the most significant, byte of 'a' (if your
    > system is little-endian). What else would I use?


    I was/am confused why you are adding the mere value "sizeof(a)-1". This
    seems to be accomplishing a bit shift of "(sizeof(a)-1)" bytes (bytes,
    not bits!) left, because of what I said above.

    >
    >>I'm sorry, but this particular syntax and bit formatting is foreign to
    >>me. Thanks.

    >
    >
    > OK, you could write
    >
    > char *pa = reinterpret_cast<char*>(&a) + sizeof(a) - 1; // address
    > char &ra = *pa; // get a reference from the address
    > ra = ra ^ 0x80; // flip the bit in the char using the reference.
    >
    > I just wrote it in one statement. (Of course this works only on
    > a system that is little-endian and has 8-bit chars)
    >
    > I supposed you need to read about compound assignment operators
    > as well. Have you ever seen a += b? If yes, why a ^= b looks
    > so foreign to you?


    Yes, of course I've seen "a += b". That's in piddly Java, my 1st piddly
    language. I've just never seen "(a + c) += b", which is more similar to
    your "(*(reinterpret_cast<char*>(&a) + sizeof(a)-1) ^= 0x80)". (a + c)
    is not an l-value, so I didn't see how (*(reinterpret_cast<char*>(&a) +
    sizeof(a)-1) could be an l-value. Seems this is one more rule that is
    different for pointers than for primitives.

    ** Why is (*(reinterpret_cast<char*>(&a) + sizeof(a)-1) an l-value,
    allowed to be used on the LHS of an assignment?????

    I took a guess, thinking that one would unroll "(a + c) += b" (if it
    were legal, which it's *not*) as "a = (a + c) + b" (where the pluses
    don't necessarily have to be the same operator). So, I unrolled
    "(*(reinterpret_cast<char*>(&a) + sizeof(a)-1) ^= 0x80)" as "a =
    (*(reinterpret_cast<char*>(&a) + sizeof(a)-1) ^ 0x80)", but that was
    wrong (i.e., I got a different bit representation than yours).

    > If not, well, open your textbook...


    If only I knew what to look up. :) It's all about knowing the buzz
    words, the Google terms, the jargon. I've got "The C++ Programming
    Language" by Bjarne Stroustrup, but I haven't seen anything more than
    the basic "a += b" in that.

    I ask questions only when I don't know what to look up, or when I'm
    confused by what I've looked up. Having been a teaching assistant, I
    understand the annoyance of having students ask questions unprepared.

    I'll get it eventually...

    Suzanne
    Suzanne Vogel, Jul 7, 2003
    #14
  15. "Suzanne Vogel" <> wrote in message
    news:3f08cba3$...
    > Thanks for the suggestion, but this prints out gibberish (8 Å @) on my
    > computer. And adding static_cast<unsigned char> within the loop didn't
    > help -- and it shouldn't, because p is already an unsigned char.
    >
    > Instead of printing each char p out straight as it is, I have to do
    > bitwise-AND with a bit mask to extract the bits one by one. (And I use
    > long, instead of char, although that might be unnecessary.)



    With C++ you can avoid the dangerous low level stuff and play more safely.
    Check this:


    #include <iostream>
    #include <bitset>
    #include <limits>


    int main()
    {
    using namespace std;

    double d=999;

    unsigned char *p=reinterpret_cast<unsigned char *>(&d);

    // There are systems where 1 byte is more than 8 bits
    bitset<numeric_limits<unsigned char>::digits> byte;

    for(unsigned i=0; i<sizeof(d); ++i)
    {
    byte=p;

    for(unsigned j=0; j<byte.size(); ++j)
    cout<<byte;
    }

    cout<<endl;
    }


    It does what you want elegantly and efficiently.




    --
    Ioannis

    * Programming pages: http://www.noicys.freeurl.com
    * Alternative URL 1: http://run.to/noicys
    * Alternative URL 2: http://www.noicys.cjb.net
    Ioannis Vranos, Jul 7, 2003
    #15
  16. "Ioannis Vranos" <> wrote in message
    news:3f0952e6$0$22136$...
    > "Suzanne Vogel" <> wrote in message
    > news:3f08cba3$...
    > > Thanks for the suggestion, but this prints out gibberish (8 Å @) on my
    > > computer. And adding static_cast<unsigned char> within the loop didn't
    > > help -- and it shouldn't, because p is already an unsigned char.
    > >
    > > Instead of printing each char p out straight as it is, I have to do
    > > bitwise-AND with a bit mask to extract the bits one by one. (And I use
    > > long, instead of char, although that might be unnecessary.)

    >
    >
    > With C++ you can avoid the dangerous low level stuff and play more safely.
    > Check this:
    >
    >
    > #include <iostream>
    > #include <bitset>
    > #include <limits>
    >
    >
    > int main()
    > {
    > using namespace std;
    >
    > double d=999;
    >
    > unsigned char *p=reinterpret_cast<unsigned char *>(&d);
    >
    > // There are systems where 1 byte is more than 8 bits
    > bitset<numeric_limits<unsigned char>::digits> byte;
    >
    > for(unsigned i=0; i<sizeof(d); ++i)
    > {
    > byte=p;
    >
    > for(unsigned j=0; j<byte.size(); ++j)
    > cout<<byte;



    The above line should be: cout<<byte[j];


    > }
    >
    > cout<<endl;
    > }
    >
    >
    > It does what you want elegantly and efficiently.
    >
    >
    >
    >
    > --
    > Ioannis
    >
    > * Programming pages: http://www.noicys.freeurl.com
    > * Alternative URL 1: http://run.to/noicys
    > * Alternative URL 2: http://www.noicys.cjb.net
    >
    Ioannis Vranos, Jul 7, 2003
    #16
  17. Thanks, Ioannis! This also answers another question of mine: How to get
    the number of bits per byte.

    Suzanne

    > With C++ you can avoid the dangerous low level stuff and play more safely.
    > Check this:
    >
    >
    > #include <iostream>
    > #include <bitset>
    > #include <limits>
    >
    >
    > int main()
    > {
    > using namespace std;
    >
    > double d=999;
    >
    > unsigned char *p=reinterpret_cast<unsigned char *>(&d);
    >
    > // There are systems where 1 byte is more than 8 bits
    > bitset<numeric_limits<unsigned char>::digits> byte;
    >
    > for(unsigned i=0; i<sizeof(d); ++i)
    > {
    > byte=p;
    >
    > for(unsigned j=0; j<byte.size(); ++j)
    > cout<<byte;
    > }
    >
    > cout<<endl;
    > }
    >
    >
    > It does what you want elegantly and efficiently.
    >
    >
    >
    >
    Suzanne Vogel, Jul 7, 2003
    #17
  18. [thanks, I think I understand] Re: reinterpret_cast - to interpretdouble as long

    Thanks, Victor. I think understand now, and I do like the one-liner
    below. I wasn't consciously inattentive (although I don't think I'm
    stupid); I was simply not in the pointer mindset and hence I was
    closed-minded, *and* I forgot that bit shifting can occur only within a
    single byte.

    double a = 0.0;
    *(reinterpret_cast<char*>(&a) + sizeof(a)-1) ^= 0x80;

    Here's what I've learned/realized (so you realize your posts were
    worthwhile):
    - 0x80 == 10000000 == a byte with 1 at the left and all the rest 0's
    - bit-shifting can occur only *within* a byte; hence 0x80 << [something]
    will give all zeros and not accomplish anything
    - adding (sizeof(a)-1) moves that many bytes left (on my system); this
    is what I meant by "bit shifting" (but "bit shifting" is the wrong
    terminology, since I'm not actually *changing* anything in memory)
    - *(a+b) is an l-value, because it's the value referenced by address a+b

    So, putting all this together, the line above does the following (on my
    system, and where I rewrite pa == reinterpret_cast<char*>(&a)):
    000000000000000000000000000000000000000000000000000000000000000000000000
    | |
    +-(pa + sizeof(a)-1) +-pa

    100000000000000000000000000000000000000000000000000000000000000000000000
    | |
    +-*((pa + sizeof(a)-1) ^ 0x80)-----------------------------------------+

    If this is correct, I don't know why I didn't see it sooner; if this is
    *not* correct, then I must be crazy.....
    ......

    > Do you understand the annoyance having to repeat oneself simply
    > because of inattentiveness of the listener? :)


    Yep, sure do.

    > Good luck!


    Thanks. :)

    > Victor
    >

    Suzanne
    --
    www.cs.unc.edu/~vogel
    Suzanne Vogel, Jul 7, 2003
    #18
    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. Sydex
    Replies:
    12
    Views:
    6,452
    Victor Bazarov
    Feb 17, 2005
  2. Daniel Rudy

    unsigned long long int to long double

    Daniel Rudy, Sep 19, 2005, in forum: C Programming
    Replies:
    5
    Views:
    1,175
    Peter Shaggy Haywood
    Sep 20, 2005
  3. Replies:
    0
    Views:
    337
  4. J.M.
    Replies:
    3
    Views:
    616
    Sarath
    Mar 6, 2007
  5. Alex Vinokur
    Replies:
    1
    Views:
    565
Loading...

Share This Page