2013-03-13 1 views
2
#include <stdio.h> 

int main() 
{ 
    char str[17]; 
    getBin(3334, str); 
    printf("%s\n", str); 
    return 0; 
} 

void getBin(int num, char *str) 
{ 
    *(str+16) = '\0'; 
    int mask = 0x8000 << 1; 
    while(mask >>= 1) 
    *str++ = !!(mask & num) + '0'; 
} 

Я действительно не понимаю, как работает цикл while. Может ли кто-нибудь объяснить простым языком, что он делает? Спасибо4-значный десятичный код с 16-разрядным двоичным кодом

ответ

4

Да, конечно. Итак, 0x8000 = 8 * 16^3 = 2^15. Теперь, если вы сдвинете это налево еще раз, вы получите 2^16.

в то время как цикл непрерывно принимает маску через все значения:

  • 2^15
  • 2^14
  • 2^13 ...

Так время цикла рассматривает маску как итератор для степеней двух в регулярном целое.

Теперь, что делает !!(mask & num)? Он возвращает 1, если бит, обозначенный маской, перевернут on или 0, если это off.

Выражения !!(mask & num) возвращает 0 или 1, и добавил к коде характера 0 она возвращает код символа для 0 или для 1.

Так, например, если num=12 и mask=4, то !!(4 & 12) = !!(100 & 1100) = !!(100)= !0 = 1. Теперь, если вы добавите 1 + '0', что вы получите? Вы получаете 1+48=49, который является символьным кодом для 1.

*str++ = .. присваивает значение этой конкретной позиции в строке, а затем увеличивает указатель на следующий символ.

Вопрос: Is str null-terminated или нет?

Я думаю, что строка *(str+16) = '\0'; заботится о нулевом завершении, потому что она превентивно устанавливает пустой байт завершения.

Так что, я думаю, это объяснение фрагмента кода, который вы написали выше.

+2

Также обратите внимание, что код сработает и сгорит на 8 или 16-разрядном компьютере, где int - 16 бит. – Lundin

+0

Полезно знать. У кого-то есть лучший способ, если он работает на 16-битном микро, как MSP430? – cii

1
void getBin(int num, char *str) 

getBin() принимает ряд (num) и строку для записи (str)

*(str+16) = '\0'; 

Последний символ str установлен в NULL терминатора

int mask = 0x8000 << 1; 

Мы создаем переменную, называемую mask, и установите ее на 0x8000, сдвинутую влево на 1, что равно 0x10000. Зачем?может быть легче видеть в двоичной системе:

0x8000 => 1000 0000 0000 0000 (а затем переместить все осталось 1 место) => 0x10000

while(mask >>= 1) 

Хотя mask больше 0, то сдвиг вправо 1 бит, и сохранить результат обратно в mask. (>>= означает сдвиг вправо и сохранение). Это означает, что значения будут:


0x10000 == 1 000 0000 0000 0000 == 65536
0x8000 == 1000 0000 0000 0000 = = 32768
0x4000 == 100 0000 0000 0000 == 16384
0x2000 == 10 0000 0000 0000 == 8192
...
0x4 == 100 == 4
0x2 == 10 == 2
0x1 == 1 == 1

Наконец, на каждой из этих итераций:

*str++ = !!(mask & num) + '0'; 

Этот код принимает каждую цифру в num, AND'ing его с 1 бит, который установлен в mask и проверяет, является ли результат == 0, затем он добавляет значение символа 0 и сохраняет это окончательное число «ASCII» в строке, а затем увеличивает строку.

Давайте разберем, что вниз на один шаг за один раз:

mask & num // num is 3334 = 0011 0011 0011 0100 
      // mask starts at = 1000 0000 0000 0000 

Итак, на первой итерации значение (mask & num) является 0.

!!(x) такая же, как говорят: (x == 0 ? 0 : 1) так на первой итерации мы имеем 0 так !!(0) дает нам 0, мы хотим сохранить, что в нашу строку, но мы хотим, чтобы это было ASCII символов.ASCII символов для 0 является 0x30 поэтому мы добавляем 0x30 к 0 и получить 0x30 (или '0'), то

*str++ = '0'; 

We разыменовать str и хранить символ 0, то есть после приращения перехода к следующему символ в строке.

+0

Спасибо. Это также хороший ответ – cii

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