解码base64时的C位移位
我正在尝试用C解码base64数据。我找到了我想要使用的实现,但我不确定它到底是如何工作的,我希望能得到一些关于这里使用的通用语法的帮助/解释: 我试图理解的代码是:解码base64时的C位移位,c,base64,bit-manipulation,decode,C,Base64,Bit Manipulation,Decode,我正在尝试用C解码base64数据。我找到了我想要使用的实现,但我不确定它到底是如何工作的,我希望能得到一些关于这里使用的通用语法的帮助/解释: 我试图理解的代码是: int base64decode (char *in, size_t inLen, unsigned char *out, size_t *outLen) { char *end = in + inLen; size_t buf = 1, len = 0; while (in < end) {
int base64decode (char *in, size_t inLen, unsigned char *out, size_t *outLen) {
char *end = in + inLen;
size_t buf = 1, len = 0;
while (in < end) {
unsigned char c = d[*in++];
switch (c) {
case WHITESPACE: continue; /* skip whitespace */
case INVALID: return 1; /* invalid input, return error */
case EQUALS: /* pad character, end of data */
in = end;
continue;
default:
buf = buf << 6 | c;
/* If the buffer is full, split it into bytes */
if (buf & 0x1000000) {
if ((len += 3) > *outLen) return 1; /* buffer overflow */
*out++ = buf >> 16;
*out++ = buf >> 8;
*out++ = buf;
buf = 1;
}
}
}
if (buf & 0x40000) {
if ((len += 2) > *outLen) return 1; /* buffer overflow */
*out++ = buf >> 10;
*out++ = buf >> 2;
}
else if (buf & 0x1000) {
if (++len > *outLen) return 1; /* buffer overflow */
*out++ = buf >> 4;
}
*outLen = len; /* modify to reflect the actual output size */
return 0;
}
intbase64解码(字符*输入,大小*输入,无符号字符*输出,大小*输出){
char*end=in+inLen;
尺寸buf=1,长度=0;
while(在>16;
*out++=buf>>8;
*out++=buf;
buf=1;
}
}
}
如果(buf&0x40000){
if((len+=2)>*outLen)返回1;/*缓冲区溢出*/
*out++=buf>>10;
*out++=buf>>2;
}
否则如果(buf&0x1000){
如果(++len>*outLen)返回1;/*缓冲区溢出*/
*out++=buf>>4;
}
*outLen=len;/*修改以反映实际输出大小*/
返回0;
}
我被困在*out++=buf>>16,在我看来,out处的值将等于buff,应该是1000000向右移位16位?值中甚至没有16位,所以它不归零吗?我真的很想理解这段代码的其余部分,任何帮助都将不胜感激。提前谢谢 你可以一步一步地解决这个问题。让我们跳过空格、等号和无效字符,以及结尾填充的代码,重点关注循环和defualt子句:
size_t buf = 1;
while (in < end) {
unsigned char c
/* read next byte */
c = d[*in++];
/* append byte to number */
buf = buf << 6 | c;
/* If the buffer is full, split it into bytes */
if (buf & 0x1000000) {
*out++ = buf >> 16;
*out++ = buf >> 8;
*out++ = buf;
buf = 1;
}
}
空位在这里表示为点,它比零更容易读取。1
是哨兵值。好的,读取下一个字节,由a
表示。将缓冲区移动六位
.... .... .... .... .... .... .1.. .... // buf = buf << 6
好的,下一个字节,b:
.... .... .... .... ...1 aaaa aa.. .... // buf = buf << 6
.... .... .... .... ...1 aaaa aabb bbbb // buf = buf | 'b'
这个值现在第一次为真,这意味着我们已经读取了四个六位块,现在需要将数据写入三个八位块
.... .... .... .... .... ...1 aaaa aabb // buf >> 16
.... .... .... ...1 aaaa aabb bbbb cccc // buf >> 8
.... ...1 aaaa aabb bbbb cccc ccdd dddd // buf
这些值被写入字节,即无符号字符,这将把它们截断为最低的8位:
---- ---- ---- ---- ---- ---- aaaa aabb // (uchar) (buf >> 16)
---- ---- ---- ---- ---- ---- bbbb cccc // (uchar) (buf >> 8)
---- ---- ---- ---- ---- ---- ccdd dddd // (uchar) buf
现在,将
buf
重置为1
并读取下一个字节。0x1000000
不是二进制数,十六进制数中的每个数字代表四位。(0x1000000
is1感谢您的详细回答,现在它很有意义。我真的很感激。在我提供的链接中的其余代码中,我不太明白为什么它是一个&40000?如果我们使用的哨兵是1,这会是一个打字错误吗?另外,我看到我们&with 1000 next,我们正在做shif在那些以10、2和4表示的to语句中,ts…这是否解释了base64数字中的填充?再次感谢您的帮助,我仍在尝试计算它。@bry6891:不,这不是打字错误。位移位操作的是位,即二进制数。在C中,数字没有二进制表示,所以我们使用十六进制,其中一个数字表示四个bit.右移1基本上是2的乘法,就像十进制中的1的移位是10的乘法一样。在我上面的草图中,四个位组成的组代表一个十六进制数字。模式…1
,.1.
和分别对应于1、2、4和8。您可以看到>buf&0x40000
检查buf
中是否有三个六字节值,即我们刚刚添加的“c”。@bry6891:最后两个代码块if(buf&0x40000)
和if(buf&0x1000)
用于填充,请参阅[.填充字符=
不被视为特殊字符,它只是停止解码,但我们必须考虑buf
中尚未写入的数据。在第一种情况下,对应于一个等号,18位数据位于buf
中。我们写入两个字节,即位10-17和位2-9,这是完成的通过分别移动10和2,并转换为无符号字符
,正如我在上面的草图中所示。好的,那么0x40000实际上将是1………?这很有意义,我将4视为4,而不是“1…”;再次感谢它真的帮助我理解这一点。
.... .... .... .1aa aaaa bbbb bb.. .... // buf = buf << 6
.... .... .... .1aa aaaa bbbb bbcc cccc // buf = buf | 'c'
.... ...1 aaaa aabb bbbb cccc cc.. .... // buf = buf << 6
.... ...1 aaaa aabb bbbb cccc ccdd dddd // buf = buf | 'd'
.... ...1 aaaa aabb bbbb cccc ccdd dddd // buf
.... ...1 .... .... .... .... .... .... // 0x1000000
.... ...1 .... .... .... .... .... .... // buf & 0x1000000
.... .... .... .... .... ...1 aaaa aabb // buf >> 16
.... .... .... ...1 aaaa aabb bbbb cccc // buf >> 8
.... ...1 aaaa aabb bbbb cccc ccdd dddd // buf
---- ---- ---- ---- ---- ---- aaaa aabb // (uchar) (buf >> 16)
---- ---- ---- ---- ---- ---- bbbb cccc // (uchar) (buf >> 8)
---- ---- ---- ---- ---- ---- ccdd dddd // (uchar) buf