代码之家  ›  专栏  ›  技术社区  ›  Dominic

如何重新排列位?

  •  0
  • Dominic  · 技术社区  · 7 年前

    uint8_t c;
    uint8_t string[3];
    
    string1[2] = (((c&(1<<0))!=0)<<6)|
                 (((c&(1<<1))!=0)<<1)|
                 (((c&(1<<2))!=0)<<0)|
                 (((c&(1<<3))!=0)<<2)|
                 (((c&(1<<4))!=0)<<3)|
                 (((c&(1<<5))!=0)<<4)|
                 (((c&(1<<6))!=0)<<5)|
                 (((c&(1<<7))!=0)<<7);
    

    基本上:

    如果位1是1,则将a向左移动10次。

    有更好的解决方案吗?

    2 回复  |  直到 7 年前
        1
  •  5
  •   ikegami    7 年前
    (((c&(1<<x))!=0)<<y)
    

    也可以写成

    ((c&(1<<x)))<<(y-x))
    

    一开始,这就消除了每比特一个操作。(请记住 y-x

    但事实并非如此。如果在整个过程中应用此转换,您会注意到一些位的移位量相同。

    (( c & 0x01 ) << 6 ) |
    (( c & 0x02 )      ) |
    (( c & 0x04 ) >> 2 ) |
    (( c & 0x08 ) >> 1 ) |
    (( c & 0x10 ) >> 1 ) |
    (( c & 0x20 ) >> 1 ) |
    (( c & 0x40 ) >> 1 ) |
    (( c & 0x80 )      )
    

    我们可以将它们分组。

    (( c & 0x01 ) << 6 ) |
    (( c & 0x82 )      ) |
    (( c & 0x78 ) >> 1 ) |
    (( c & 0x04 ) >> 2 )
    

        2
  •  0
  •   ekim    6 年前

    “更好”如:“情人眼里出西施。”?

    Kernighan和Ritchie在1988年出版的第2版《C编程语言》第6章最后两节中解释了这段代码的微妙之处和特点:

    uint8_t c;
    uint8_t string[3];
    
    union { uint8_t  bits;
      struct { uint8_t t7    :1;
               uint8_t t3456 :4;
               uint8_t t2    :1;
               uint8_t t1    :1;
               uint8_t t0    :1;
             } bi;
      struct { uint8_t b7    :1;
               uint8_t b6    :1;
               uint8_t b2345 :4;
               uint8_t b1    :1;
               uint8_t b0    :1;
             } ti;
          } b,d;
    
      b.bits = d.bits = c;      // does b.ti.b1 = d.bi.t1; b.ti.b7 = d.bi.t7;
    
      b.ti.b0    = d.bi.t2;
      b.ti.b2345 = d.bi.t3456;
      b.ti.b6    = d.bi.t0;
    
      string[2] = b.bits;
    

      struct { uint8_t t0    :1;
               uint8_t t1    :1;
               uint8_t t2    :1;
               uint8_t t3456 :4;
               uint8_t t7    :1;
              } bi;
      struct { uint8_t b0    :1;
               uint8_t b1    :1;
               uint8_t b2345 :4;
               uint8_t b6    :1;
               uint8_t b7    :1;
              } ti;