Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
解码base64时的C位移位_C_Base64_Bit Manipulation_Decode - Fatal编程技术网

解码base64时的C位移位

解码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) {

我正在尝试用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) {
        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
is
1感谢您的详细回答,现在它很有意义。我真的很感激。在我提供的链接中的其余代码中,我不太明白为什么它是一个&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