【问题标题】:C - Using bit-shift operators for base conversionC - 使用位移运算符进行基本转换
【发布时间】:2023-03-07 19:55:01
【问题描述】:

我正在尝试在 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

【问题讨论】:

  • 如果你理解了位运算符的作用,那么你在代码中没有理解什么?
  • 您可以将您对&gt;&gt;&lt;&lt;&amp; 的理解添加到问题中——然后看看您是否还有问题。
  • 好的,我会以我有限的理解编辑它。再次感谢您的帮助。
  • 63 = 0b00111111,加上一些了解@Arkadiy 所说的你应该自己尝试一下。(0b00111111 这是它在 RAM 中的一个字节内存中的样子,0b 表示数字是二进制的,00111111 是二进制数)
  • 位移正如其名称所暗示的那样。 n &gt;&gt; 1 表示 n 的最低二进制位被丢弃,次高位变为最低位,依此类推。例如,00011001 &gt;&gt; 1 会产生 00001100。有符号整数类型还有更多内容(传播符号位),但本质是移位。移位和位掩码(&amp; 运算符)的组合允许您从单词中间取出一堆位并将它们视为单独的数字。

标签: c bit-manipulation shift


【解决方案1】:

首先,输入数据不是你说的十六进制。它只是以字节形式存储的数据。该代码将为您提供它的 base64 表示(尽管您发布的代码缺少将 n0n1n2n3 映射到可打印 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

【讨论】:

  • 哇,这对我来说真的很有意义。非常感谢你!我没想到它会变得那么清楚。再次感谢!
【解决方案2】:

好吧,这里有一点解释..

data[x] 是一个字符数组,一个字符通常是 8 位 ..(随机 8 位数字 01010101) n 是一个 32 位的数字,这里是一个随机的 32 位数字(01011111000011110000111100001111)认为那里有 32 位 :)

记住 n 是 32 位,数据只有 8 位。让我们看第一行

 n = data[x] << 16;

data[x]

n = 00000000 01100001 00000000 00000000

接下来是

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

这表示将下一个 char data[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 

现在重复此操作

【讨论】:

  • 哇非常彻底,太棒了!我希望我可以为绿色复选标记选择两个答案。感谢您花时间写这篇文章,这对我很有帮助。
猜你喜欢
  • 2019-07-26
  • 1970-01-01
  • 2016-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多