我正在尝试将一些数据从十六进制转换为C中的base64,我在网上找到了一个算法,但我真的想知道它是如何工作的,而不仅仅是实现它并将其解雇。如果有人可以解释以下是如何工作的,我将不胜感激。我一直在阅读关于移位操作符的内容,我似乎并不像我想的那样理解它们...它不是很适合我。
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) < dataLength)
n += data[x+2];
/* this 24-bit number gets separated into four 6-bit numbers */
n0 = (uint8_t)(n >> 18) & 63;
n1 = (uint8_t)(n >> 12) & 63;
n2 = (uint8_t)(n >> 6) & 63;
n3 = (uint8_t)n & 63;
此代码取自Wikibooks,它不是我的,我只是想了解位移以及它如何允许我转换数据。
感谢您的帮助,我真的很感激。
来源:Base64
答案 0 :(得分:5)
首先,输入数据不是十六进制,如你所说。它只是存储为字节的数据。代码将为您提供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
答案 1 :(得分:2)
好的,这里有一点解释..
data [x]是一个字符数组,一个字符是usbit 8bits ..(随机8位数01010101) n是一个32位数,这里是一个随机的32位数(01011111000011110000111100001111),认为那里有32位:)
记住n是32位,数据只有8位..让我们通过第一行
n = data[x] << 16;
&lt;&lt; 16优先于等号,因此首先评估它。
data [x]&lt;&lt; 16表示将数据[x]中的位移动到左侧16位。 假设data [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];
让我们在这里做同样的事情,注意没有位移,因为n的最后8位是免费的!我们需要做的就是将它添加到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
现在重复此操作