C – Использование операторов бит-сдвига для базового преобразования

Я пытаюсь преобразовать некоторые данные из hex в base64 в C, я нашел алгоритм онлайн, но мне очень хотелось бы знать, как это работает, а не просто внедрять его и увольнять. Если бы кто-то мог объяснить, как работает следующее, я был бы признателен. Я читал о операторах смены, и я, кажется, не понимаю их так сильно, как я думал, что сделал … это не совсем для меня.

for (x = 0; x < dataLength; x += 3) { /* these three 8-bit (ASCII) characters become one 24-bit number */ n = data[x] << 16; if((x+1) < dataLength) n += data[x+1] << 8; if((x+2) > 18) & 63; n1 = (uint8_t)(n >> 12) & 63; n2 = (uint8_t)(n >> 6) & 63; n3 = (uint8_t)n & 63; 

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

Спасибо за вашу помощь, я очень ценю это.

Источник: Base64

    Прежде всего, входные данные не являются шестнадцатеричными, как вы говорите. Это просто данные, хранящиеся в байтах. Код предоставит вам представление base64 (хотя в коде, который вы указали, отсутствует часть, которая будет отображать n0 , n1 , n2 , n3 для печатных символов ASCII).

    Предположим, что первые три байта ввода (в двоичном представлении каждая буква представляет собой 0 или 1):

     abcdefgh, ijklmnop, qrstuvwx 

    Первая часть кода объединит их с одним 24-битным номером. Это делается путем сдвига первого из 16 бит влево, а второго – 8 бит влево и добавления:

      abcdefgh0000000000000000 (abcdefgh << 16) + 00000000ijklmnop00000000 (ijklmnop << 8) 0000000000000000qrstuvwx ------------------------ abcdefghijklmnopqrstuvwx 

    Затем он отделяет это на четыре 6-битных числа путем смещения и и. Например, второе число вычисляется путем смещения 12 бит вправо и и с 111111

     n = abcdefghijklmnopqrstuvwx n>>12 = 000000000000abcdefghijkl 63 = 000000000000000000111111 And'ing gives: 000000000000000000ghijkl 

    Хорошо, вот немного объяснений ..

    data [x] – массив символов, char – usuall 8bits .. (random 8bits number 01010101) n – это 32-битное число, это случайное 32-битное число (01011111000011110000111100001111), думаю, там 32 бита 🙂

    помните, что n – 32 бит, а данные – всего 8 бит .. позволяет пройти первую строку

      n = data[x] << 16; 

    << 16 имеет приоритет над знаком равенства, поэтому его сначала оценивают.

    данные [x] << 16 означает перемещение бит в памяти, данные [x] представляют на 16 бит слева. предположим, что данные [x] = 'a' представлены в памяти 01100001 (1 байт), поэтому перемещение на 16 бит влево

     n = 00000000 01100001 00000000 00000000 

    следующий у нас есть

     if((x+1) < dataLength) n += data[x+1] << 8; 

    это говорит о перемещении следующих данных символа [x + 1] 8 бит и добавлении его к n; поэтому сначала переместите его на 8 бит

     ( I assumed it was 'a' again) 00000000 00000000 01100001 00000000 (this is done in some register in your processor) 

    теперь добавим его в n

     00000000 01100001 01100001 00000000 

    Следующая часть

      if((x+2) < dataLength) n += data[x+2]; 

    давайте сделаем то же самое здесь, заметьте, что нет смещения бит, так как последние 8 бит n бесплатны! все, что нам нужно сделать, это добавить его в n

    b = 01100010 (предполагаемые данные [x + 2] = 'b'), добавляя его к n

      00000000 01100001 01100001 01100010 

    отлично, так что теперь у нас есть 24-битный номер (на самом деле n - 32 бит, но последние 24 бита - это то, что нам нужно)

    следующая часть

     n0 = (uint8_t)(n >> 18) & 63; (take note n0 is only 8bits wide or a single unsigned byte) take n and move it to the left by 18bits and "and" it with 63 n = 00000000 01100001 01100001 01100010 n moved 18bits to right is 00000000 00000000 00000000 00011000 now n is cast to an unsigned int of 8bits (uint8_t) so now it becomes 00011000 last part is the & operator(bitwise and) 00011000 & 00111111 n0= 00011000 

    теперь повторите это для остальных