在unsigned int中使用第一位作为标志

时间:2019-06-20 19:58:07

标签: c++ c++11 bit

如果作为服务器的客户端应该为它们的加密密钥重新键入密钥,则我尝试将unsigned int的第一位用作标志。我想将其余的unsigned int用作正在发送的剩余数据的长度。

目前,我正在尝试此操作,但似乎不起作用。

unsigned int payloadLength;
read(sock, &payloadLength, sizeof(payloadLength));
short bit = (payloadLength >> 0) & 1U; // get first bit

payloadLength &= 1UL << 0; // set first bit to 0
payloadLength = ntohl(payloadLength);

if (bit == 1) 
   //rekey
else
  //read more data

重命名标志似乎设置正确,但是当尝试获取长度时,它总是以错误的数字结尾。

编辑:我应该澄清我的意思是最高有效位,而不是第一位

2 个答案:

答案 0 :(得分:3)

让我们看一下这段代码:

short bit = (payloadLength >> 0) & 1U; // get first bit
payloadLength &= 1UL << 0; // set first bit to 0
payloadLength = ntohl(payloadLength);

尽管以这种方式订购这些语句是完全合法的,但仍有可能无法按照您希望的方式工作。具体来说,您可能想解码有效载荷以使用主机字节顺序 ,然后再开始戳戳和探查字节。否则,如果您将数据从一个系统发送到另一个系统,则有可能会读回错误的位。但这并不是很难解决-只需将最后一个对payloadLength进行解码的语句移到顶部,就像这样:

/* CAUTION: This still has errors! */
payloadLength = ntohl(payloadLength);
short bit = (payloadLength >> 0) & 1U; // get first bit
payloadLength &= 1UL << 0; // set first bit to 0

接下来,存在一个有关您要尝试读取的位的问题。您似乎正在尝试读取数字的最低有效位。如果是这种情况,则无需包含任何位移,因为零位位移不会产生任何影响。让我们删除它们,给出以下内容:

/* CAUTION: This still has errors! */
payloadLength = ntohl(payloadLength);
short bit = payloadLength & 1U; // get first bit
payloadLength &= 1UL; // set first bit to 0

您提取号码最后一位的代码是正确的。它将屏蔽掉最低位以外的所有内容,然后将值存储在变量bit中。 (出于好奇,您是否有任何理由将其存储为short?如果您正在寻找布尔值“我是否需要对此重新编码?”,您可能只想使用{{1 }}并写类似

bool

不过,这取决于您。)

但是,您要清除 最后一位的代码不正确。现在,当你写

bool reencode = (payloadLength & 1U) != 0;

您实际上在执行与预期相反的操作-首先清除所有 位。这是因为,如果您将payloadLength &= 1UL; // set first bit to 0 与一个值进行“与”运算,则payloadLength中的每个位都将为零,payloadLength中等于1的位除外。但是,1UL在最后位置只有1位。您可能打算写类似

1UL

〜运算符将掩码的位翻转。总体而言,这将为您提供以下信息:

payloadLength &= ~1UL; // set first bit to 0

不过,我还有最后一个问题。通过以这种方式重新使用数字的最低位,您就要求有效载荷长度必须始终是偶数,因为您要利用有效载荷长度的1比特来编码是否要更新密钥。如果您对此表示满意,那就太好了!您无需执行任何操作。

另一方面,如果这是一个问题,那么您有几个选择,我将留给您选择:

  1. 使用最高有效位代替使用最低有效位。但是,如果您尝试发送大小为2 31 或更高的有效负载,则会导致问题。

  2. 使用最低有效位,但数字的高31位代表实际有效载荷长度。要提取有效载荷长度,只需将所有内容移到一个位置即可。这样做的缺点是不支持2 31 或更大的有效载荷。

  3. 根本不使用位来对此进行编码!而是发送有效载荷长度,然后使有效载荷以标头开头,该标头告诉您是否进行密钥更新等。这会为每个有效载荷使用更多字节,但在将来也为您提供更大的灵活性(如果需要发送其他标志,好吗?)

希望这会有所帮助!

答案 1 :(得分:1)

payloadLength &= 1UL << 0;将除第一个以外的所有其他位清零。 payloadLength &= ~1UL;将第一位清零。