2013-11-21 8 views
4

Во время чтения Hacking: Искусство эксплуатации (! Замечательная книга), я наткнулся на эту функцию:Как работает эта функция?

void binary_print(unsigned int value) { 
    unsigned int mask = 0xff000000; // Start with a mask for the highest byte. 
    unsigned int shift = 256*256*256; // Start with a shift for the highest byte. 
    unsigned int byte, byte_iterator, bit_iterator; 

    for(byte_iterator=0; byte_iterator < 4; byte_iterator++) { 
     byte = (value & mask)/shift; // Isolate each byte. 
     printf(" "); 
     for(bit_iterator=0; bit_iterator < 8; bit_iterator++) { // Print the byte's bits. 
     if(byte & 0x80) // If the highest bit in the byte isn't 0, 
      printf("1");  // print a 1. 
     else 
      printf("0");  // Otherwise, print a 0. 
     byte *= 2;   // Move all the bits to the left by 1. 
     } 
     mask /= 256;  // Move the bits in mask right by 8. 
     shift /= 256;  // Move the bits in shift right by 8. 
    } 
} 

Вот ввода-вывода таблицы для функции:

= = = = = = = = = = = = = = = = = = = = = = 
INPUT : OUTPUT 
= = = = = = = = = = = = = = = = = = = = = = 
0  : 00000000 00000000 00000000 00000000 
2  : 00000000 00000000 00000000 00000010 
1  : 00000000 00000000 00000000 00000001 
1024 : 00000000 00000000 00000100 00000000 
512 : 00000000 00000000 00000010 00000000 
64 : 00000000 00000000 00000000 01000000 
= = = = = = = = = = = = = = = = = = = = = = 

По это я знаю, что binary_print() преобразует десятичную в двоичную.

Но я не понимаю как точно функция находит правильный ответ. В частности:

  • Что такое маска? Как автор пришел к значению 0xff000000? (0xff000000 приближается к 2^32, максимальное значение int в системе)
  • Что такое сдвиг? Зачем его инициализировать до 256^3? (мне, кажется, что это что-то делать с места весов в шестнадцатеричной)
  • Что на самом деле происходит в этих строках:
    • байт = (значение & маска)/сдвиг
    • байт & 0x80

Короче говоря, я хотел бы понять метод binary_print() используется, чтобы сделать преобразования.

+2

Есть ли какие-либо @ e-satis в мире C тоже :)? (http://stackoverflow.com/users/9951/e-satis).Например, для этого вопроса нужен ответ, например, ответ на ключевое слово yield python - http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained/231855#231855 – Yavar

+0

См. MSDN: [Побитовые операторы ] (http://msdn.microsoft.com/en-us/library/17zwb64t.aspx) и [Побитовые операторы сдвига] (http://msdn.microsoft.com/en-us/library/f96c63ed.aspx) И Википедия: [Подсчет в двоичном формате] (http://en.wikipedia.org/wiki/Binary_number#Counting_in_binary) :) – parrowdice

ответ

6

Немного mask (на 32-разрядных машинах) 0xff000000 имеет все 1 бит для максимального байта. И shift инициализируется значением 0x1000000 (то есть 256 * 256 * 256).

byte = (value & mask)/shift использует бит - и извлекает биты маски, а затем сдвигает их, чтобы получить значение между 0 и 0xff (установка в 8-битовом байте).

Обратите внимание, что для unsigned номера mask /= 256 - это то же самое, что и mask = mask >> 8 (а компилятор обычно оптимизирует первый и второй).

Лучший способ понять, что именно происходит может скомпилировать код со всеми предупреждениями и отладочной информации (например, gcc -Wall -g) и использовать отладчик (gdb), чтобы запустить программу шаг за шагом и отобразить соответствующее состояние ,

3

Это скорее комментарий, чем ответ. Я не видел эту книгу, поэтому я понятия не имею, что должен показать этот фрагмент кода, но это очень сложный способ получения желаемого результата.

Вот более простой:

void binary_print(unsigned value) { 
    for (unsigned mask = 0x80000000; // High order bit 
     mask;      // While we have a bit 
     mask >>= 1) {    // Shift right to next bit position 
    if (value & mask) putchar('1'); // Bit is set: print a 1 
    else    putchar('0'); // Bit is not set: print a 0 
    if (mask & 0x01010100) putchar(' '); // A space if we just did the 
             // low order bit of some byte 
    } 
} 

Помимо хак в последней строке, которая не является слишком странно, я надеюсь, я думаю, что логика должна быть довольно просто для тех, кто знаком с битым operations.printf is overkill

Смежные вопросы