【问题标题】:C: Building a byteC:构建一个字节
【发布时间】:2011-01-24 12:49:29
【问题描述】:

我有一个包含 16 个元素的数组。我想将这些评估为布尔值 0 或 1,然后将其存储在 2 个字节中,以便我可以写入二进制文件。我该怎么做?

【问题讨论】:

  • @Neil,你为什么这么问?可能 OP 不知道按位运算。
  • @Nick 提出问题的想法是,它们应该在某种意义上扩展对底层语言/技术的理解。这个问题不是 - 简单地提出问题绝不应该成为支持的理由。
  • 我对此表示赞同,因为它就是这样做的——通过提供的答案扩展读者的知识。按位运算并不是最容易理解的概念(在我看来),所以我认为这是一个很好的问题。为什么不应该简单地提出问题作为支持的理由?只要是能帮助别人的问题,何乐而不为呢?
  • @Neil,当然,我同意这一点。不过,它们并不是获得支持的唯一原因。
  • @Neil 我真的没有任何计划。你让这听起来像是我们都在竞选 SO 的总裁,我们有不同的、相互矛盾的议程:)。如果你对这个网站有远见,我相信它比我能想到的任何东西都要好,我祝你一切顺利。我只是认为这是一个很好的问题,因为根据我的经验,在课堂上对位运算符的讨论还不够。没有必要因为投票而像那样妖魔化我,是吗?

标签: c binary byte


【解决方案1】:

你的意思是这样的吗?

unsigned short binary = 0, i;
for ( i = 0; i < 16; ++i )
  if ( array[i] )
    binary |= 1 << i; 

// the i-th bit of binary is 1 if array[i] is true and 0 otherwise.

【讨论】:

    【解决方案2】:

    你必须使用bitwise operators

    这是一个例子:

    int firstBit = 0x1;
    int secondBit = 0x2;
    int thirdBit = 0x4;
    int fourthBit = 0x8;
    
    int x = firstBit | fourthBit; /*both the 1st and 4th bit are set */
    int isFirstBitSet = x & firstBit; /* Check if at least the first bit is set */
    

    【讨论】:

      【解决方案3】:
      int values[16];
      int i;
      unsigned short word = 0;
      unsigned short bit = 1;
      
      for (i = 0; i < 16; i++)
      {
          if (values[i])
          {
              word |= bit;
          }
      
          bit <<= 1;
      }
      

      【讨论】:

        【解决方案4】:

        此解决方案避免在循环内使用 if:

        unsigned short binary = 0, i;
        for ( i = 0; i < 16; ++i )
          binary |= (array[i] != 0) << i;
        

        【讨论】:

        • 这意味着循环将零向左移动,或者将结果转换为“二进制”,而 IVlad 的解决方案仅处理设置位。目前尚不清楚主要流水线架构的好处在哪里,但名义上对具有许多零的数组执行较少的操作是有好处的。
        【解决方案5】:

        用两个字节声明一个数组result,然后循环遍历源数组:

        for (int i = 0; i < 16; i++) {
          // calclurate index in result array
          int index = i >> 3;
          // shift value in result
          result[index] <<= 1;
          // check array value
          if (theArray[i]) {
            // true, so set lowest bit in result byte
            result[index]++;
          }
        }
        

        【讨论】:

        • 为什么投反对票?如果你不说你不喜欢什么,那是毫无意义的。
        • 我没有以任何方式投票,但我猜这是因为你使用了一个数组,你甚至没有提到它的类型。我猜这是一个 char 数组,但 OP 可能不知道。无论哪种方式,您都可以在没有数组的情况下执行此操作。您选择使用数组有什么原因吗?
        • @IVlad:OP 专门要求两个字节,将它们存储在数组中的逻辑方式。数据类型可以是任何能够处理字节的东西,但 char 是一个明显的选择。
        • 嗯,短片也可以,不是吗?无论如何,我 +1,我想 char 数组确实更适合:)。
        • OP 指定了一个包含 16 个元素的数组作为输入/他没有指定什么类型,但这实际上并不重要,只要它可以被评估为零或非零,因此转换为布尔值。
        【解决方案6】:

        类似的东西。

        int values[16];
        int bits = 0;
        for (int ii = 0; ii < 16; ++ii)
        {
            bits |= (!!values[ii]) << ii;
        }
        
        unsigned short output = (unsigned short)bits;
        

        表达式 (!!values[ii]) 强制值为 0 或 1,如果您确定 values 数组已经包含 0 或 1 而没有其他内容,您可以离开 !!

        如果您不喜欢 !!句法。

        int values[16];
        int bits = 0;
        for (int ii = 0; ii < 16; ++ii)
        {
            bits |= (values[ii] != 0) << ii;
        }
        
        unsigned short output = (unsigned short)bits;
        

        【讨论】:

        • 使用!!有什么意义?一个简单的if 语句使这更容易阅读。顺便说一句,您的 for 循环无法编译。
        • if 语句在内循环中添加一个分支。
        • 甜蜜。建议一个更优的解决方案并为此投票!谢谢 LVlad!
        • 真的,更优化?它只是一个由 16 个元素组成的数组,我怀疑是否有任何平台可以让您注意到不同之处。它只是不必要地混淆了这里的代码。
        • 确实优化了很多。如果你不相信我,你自己测试一下。像这样的小功能往往只使用一次。或者它们一直被使用,突然内部循环中的这个分支开始变得重要。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多