views:

142

answers:

3

In 'Thinking in C++' by Bruce Eckel, there is a program given to print a double value
in binary. (Chapter 3, page no. 189)

int main(int argc, char* argv[]) 
{  
  if(argc != 2) 
  {  
    cout << "Must provide a number" << endl;  
    exit(1);  
  }  
  double d = atof(argv[1]);  
  unsigned char* cp = reinterpret_cast<unsigned char*>(&d);  
  for(int i = sizeof(double); i > 0 ; i -= 2)   
  {  
    printBinary(cp[i-1]);  
    printBinary(cp[i]);  
  }
}

Here while printing cp[i] when i=8 (assuming double is of 8 bytes), wouldn't it be undefined behaviour?
I mean this code doesn't work as it doesn't print cp[0].

+1  A: 

It looks like a typo in the book's code. The second call should probably be printBinary(cp[i-2]).

This is a bit wierd though, because they're reversing the byte order compared to what's actually in memory (IEEE 754 floating point numbers have no rules about endianness, so I guess it's valid on his platform), and because he's counting by 2 instead of just 1.

It would be simpler to write

for(int i = 0; i != sizeof(double) ; ++i)    printBinary(cp[i]);

or (if reversing the bytes is important) use the standard idiom for a loop that counts down

for(int i = sizeof(double); (i--) > 0;)      printBinary(cp[i]);
Ken Bloom
Good answer - since it says pretty much everything I said.
Jonathan Leffler
+4  A: 

A1: Yes, it would be undefined behaviour when it accesses cp[8].

A2: Yes, it also does not print cp[0].

As shown, it prints bytes 7, 8, 5, 6, 3, 4, 2, 1 of the valid values 0..7. So, if you have copied the code correctly from the book, there is a bug in the book's code. Check the errata page for the book, if there is one.

It is also odd that it unwinds the loop; a simpler formulation is:

for (int i = sizeof(double); i-- > 0; )
    printBinary(cp[i]);

There is also, presumably, a good reason for printing the bytes in reverse order; it is not obvious what that would be.

Jonathan Leffler
Reverse byte order will change the endianness as it prints. I assume the author wanted the bits to be displayed in a certain order, and he also assumed those running the code would use an endian that would mess that up. Or maybe it's just an example of looping backwards for the hell of it.
GMan
@Gman: as I don't have the book, I don't know what Bruce Eckels said was the reason for doing things in reverse - or, as written, in a weird byte order similar to a PDP-11 'long'. But yes, there are a number of possible reasons, and we can hope that the book tells the reader why, even though this question does not (and probably should not) do so.
Jonathan Leffler
A: 

You can do this in an endian-independent way, by casting the double to an unsigned long long. Then you can use simple bit shifting on the integer to access and print the bits, from bit 0 to bit 63.

(I've written a C function called "print_raw_double_binary() that does this -- see my article Displaying the Raw Fields of a Floating-Point Number for details.)

Rick Regan