двойная печать в двоичном формате - PullRequest
4 голосов
/ 02 мая 2010

В «Мышлении в C ++» Брюса Эккеля есть программа для печати двойного значения
в двоичном (Глава 3, стр. № 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]);  
  }
}

Здесь, при печати cp [i], когда i = 8 (при условии, что double равен 8 байтам), не будет ли это неопределенным поведением?
Я имею в виду, что этот код не работает, так как он не печатает cp [0].

Ответы [ 3 ]

4 голосов
/ 02 мая 2010

A1: Да, при обращении к cp [8] было бы неопределенное поведение.

A2: Да, он также не печатает cp [0].

Как показано, он печатает байты 7, 8, 5, 6, 3, 4, 2, 1 действительных значений 0..7. Итак, если вы правильно скопировали код из книги, в коде книги есть ошибка. Проверьте страницу с ошибками для книги, если она есть.

Также странно, что он разматывает петлю; более простая формулировка:

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

Существует также, по-видимому, веская причина для печати байтов в обратном порядке; не очевидно, что это будет.

2 голосов
/ 02 мая 2010

Похоже на опечатку в коде книги. Второй вызов, вероятно, должен быть printBinary(cp[i-2]).

Это немного странно, потому что они меняют порядок байтов по сравнению с тем, что на самом деле находится в памяти (числа с плавающей запятой IEEE 754 не имеют правил о порядке байтов, поэтому я думаю, что он действителен для его платформы), и потому что он считает на 2 вместо 1.

Было бы проще написать

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

или (если важно поменять местами байты) используйте стандартную идиому для цикла, который ведет обратный отсчет

for(int i = sizeof(double); (i--) > 0;)      printBinary(cp[i]);
0 голосов
/ 03 мая 2010

Вы можете сделать это независимо от порядка байтов, приведя двойное к длинному без знака. Затем вы можете использовать простое смещение битов для целого числа для доступа и печати битов от 0 до 63.

(я написал функцию C с именем print_raw_double_binary (), которая делает это - см. Мою статью Отображение необработанных полей числа с плавающей запятой для получения подробной информации.)

...