如何重新排列位?
How to rearrange bits?
我必须重新排列一个字节中的位。我这样解决了问题:
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);
基本上:
如果bit0为1,将a向左移动6次
如果bit1为1,则向左移动1 0次。
....
有更好的解决方案吗?
(((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 )
我们将 30 个操作减少到 10 个。
"Better" 如:"Beauty is in the eye of the beholder."?
简单吗?另一种方式:(使用 "no"!? 赋值以外的操作?)
Kernighan 和 Ritchie 的 1988 年第 2 版 "The C Programming Language" 在第 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;
我必须重新排列一个字节中的位。我这样解决了问题:
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);
基本上:
如果bit0为1,将a向左移动6次
如果bit1为1,则向左移动1 0次。 ....
有更好的解决方案吗?
(((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 )
我们将 30 个操作减少到 10 个。
"Better" 如:"Beauty is in the eye of the beholder."?
简单吗?另一种方式:(使用 "no"!? 赋值以外的操作?)
Kernighan 和 Ritchie 的 1988 年第 2 版 "The C Programming Language" 在第 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;