|
位运算 百度百科如下: 位操作的优势
下面的a和b都是整数类型,则:
C语言中位运算符之间,按优先级顺序排列为
常见的二进制位的变换操作
对于除0以外的任意数x,使用x&1==1作为逻辑判断即可 if (x&1==1)3 ~# D9 t% V) k. |& B2 d{ } j1 o! b4 ^# z. Q* T
比如第7位, 0x40转到二进制是0100 0000,代表第7位是1. if (n&0x40)$ t1 S- L9 |) ]2 v, _: N{ //TODO:添加你要处理的代码' G$ v2 |- Q7 A+ B. Q }* k# J- ^9 p9 C1 d
(x >> 8) & 0x000000ff /* 获取第1个字节 */1 _* ?& | Q, H4 l. L: X- \5 a (x >> 16) & 0x000000ff /* 获取第2个字节 */8 x- O) M4 o8 N" ?, A (x >> 24) & 0x000000ff /* 获取第3个字节 */
if (n <= 0) return false;& e1 Q7 I4 Y' s% s! ]% I8 V return (n & (n - 1)) == 0;( U: @& `2 E4 W+ l+ U6 l0 [ }; Z0 K& V1 U" O# ?" ^$ ?
int Yu(int num,int n) { int i = 1 << n; return num&(i-1);5 T8 J! l9 H& x6 ` }, k; U2 H; R1 f1 y
比如说16位二进制数A:1001 1001 1001 1000,如果来你想获A的哪一位的值,就把数字B:0000 0000 0000 0000的那一位设置为1. 比如说我想获得A的第三位就把B的第三位数字设置为1,则B为0000 0000 0000 0100,设置完之后再把A、B求与, 其结果若为0,说明A的第三位为0,其结果为1,说明A的第三位为1. 同理:若要获得A的第五位,就把B设置为0000 0000 0001 0000,之后再求与。 通常在我们的程序中,数字B被称为掩码,其含义是专门用来测试某一位是否为0的数值。
利用x=x&(x-1),会将x用二进制表示时最右边的一个1变为0,因为x-1会将该位变为0. int Count(int x){ int sum=0;! K6 X. n& F- Q2 X0 e) J while(x) { sum++;2 v5 H& { I3 y0 o4 S/ S x=x&(x-1); }. L2 a5 Q( w* L( G6 @3 n return sum; }9 |! Q, b# \+ T or操作
当把二进制当作集合使用时,可以用or操作来增加元素。合并编码 在对字节码进行加密时,加密后的两段bit需要重新合并成一个字节,这时就需要使用or操作。
{0 V3 ]% I- N3 J# P( C! \. M int count = 0;5 O z* U1 k. d* n* o4 c while (x + 1) { count++; x |= (x + 1);; l2 h/ Y2 e% t5 g }: I9 B# I' Y3 Y return count; } xor操作
a ^= b;5 C9 |9 ^/ I- }$ b0 u: |( g8 ] b ^= a;3 W4 O9 d& ~9 h* F( j+ L+ @* L7 k a ^= b; }
bool f = ((x ^ y) < 0); // true8 q% }! \( T" s- }5 x. G" q int x = 3, y = 2;9 f9 b8 |4 ]1 s8 X; L3 I" z4 K/ V bool f = ((x ^ y) < 0); // false
将需要加密的内容看做A,密钥看做B,A ^ B=加密后的内容C。而解密时只需要将C ^ 密钥B=原内容A。如果没有密钥,就不能解密! #include <stdio.h>#include <stdlib.h> #include <string.h># h( U4 v* Q- z v #define KEY 0x86* t* o" i5 M$ H E1 d int main() { char p_data[16] = {"Hello World!"}; char Encrypt[16]={0},Decode[16]={0};! j% G7 c3 x3 k1 d# @9 S int i;8 q* ~% }9 J( |+ h 6 T1 R( v5 x5 L! H! E) p0 D W for(i = 0; i < strlen(p_data); i++)5 H2 n% M2 I9 F; o {, i- j G. m: ?# x9 I( F Encrypt = p_data ^ KEY;. N3 _0 D/ l% e% T- \ }. ?6 N! b) M! ?/ r& `+ u$ Z3 s0 b [ 7 J- ^' y4 z7 p for(i = 0; i < strlen(Encrypt); i++) { Decode = Encrypt ^ KEY;0 V+ o5 h( @7 r" k } 7 s6 |; z5 x: X* _+ G printf("Initial date: %s\n",p_data);( z, Q- E" k9 m# B printf("Encrypt date: %s\n",Encrypt); printf("Decode date: %s\n",Decode);3 N& W1 L" ^7 v6 V X7 j- l return 0; }
利用了二进制数的性质:x^y^y = x。我们可见,当同一个数累计进行两次xor操作,相当于自行抵销了,剩下的就是不重复的数
int tmp = arr[0]; for(int i = 1;i < arr.length; i++){ T# n# l! D0 X8 Z% \ tmp = tmp ^ arr;, k) P7 Q. F5 C0 E }) \) V" f% \9 T0 I) f% R return tmp; } not操作
return ~a + 1; } t1 o$ I* b+ j7 T5 s& {
{" z& {5 x% A7 b9 \) Q return (n ^ (n >> 31)) - (n >> 31);. [3 T7 `+ a V4 L3 e } 也可以这样使用 int abs(int n){ int i = n >> 31; return i == 0 ? n : (~n + 1); }/ L- [: J s! r
将1左移m-1位找到第m位,得到000...1...000, n在和这个数做或运算 int setBitToOne(int n, int m){ return n | (1 << (m-1));1 G1 z0 Z( F5 w; }; C$ M }: i: q7 X+ ~; D- V& ?& A 同理从低位到高位,将n的第m位置0,代码如下 int setBitToZero(int n, int m); f1 a' l1 p$ S2 o( W{ return n & ~(1 << (m-1)); }# N, ]- e6 ~8 c D3 `2 o: b! m shl操作 & shr操作
a = (a >> 8) | (a << 8);2 x/ A/ q- F1 } n
a = ((a & 0xAAAA) >> 1) | ((a & 0x5555) << 1); a = ((a & 0xCCCC) >> 2) | ((a & 0x3333) << 2); a = ((a & 0xF0F0) >> 4) | ((a & 0x0F0F) << 4);3 M# x: a) p: W1 \& A a = ((a & 0xFF00) >> 8) | ((a & 0x00FF) << 8);( U# U2 P5 J0 l( R Z. O- N! q2 X
{ return (1 << 31) - 1;//2147483647, 由于优先级关系,括号不可省略 } int getMinInt()2 q$ ]6 f! U* b. ^ y { return 1 << 31;//-2147483648 }
int pow(int m , int n){ int sum = 1; while(n != 0){# E- G5 R: {4 S* x8 _% J7 u if(n & 1 == 1){ sum *= m;/ S5 x( ?+ i( n) ?9 ] } m *= m; n = n >> 1;7 `0 s1 f; N: W0 W } ' q* }# A; o' G7 z% ?* r2 c" s return sum; }
n |= n >> 1;( K' |) k6 d2 ?6 u$ C n |= n >> 2;! b# }$ e+ _- g: i n |= n >> 4;( y$ o* L9 `" r1 l% J3 Q l# H n |= n >> 8 // 整型一般是 32 位,上面我是假设 8 位。& r7 q- B* W4 M; ?# b, E return (n + 1) >> 1;3 S& {3 r/ u2 n% J* B/ e. u }
{: i+ v% y+ w4 F8 V int n;. L5 m7 K/ k1 B1 i: |; i5 n ( f& x. r# \ z& E if (x == 0) return(32);2 T5 L7 Z6 v- k" \ l n = 1;$ E7 ^3 e3 T, B2 U9 e% T if ((x >> 16) == 0) {n = n +16; x = x <<16;} if ((x >> 24) == 0) {n = n + 8; x = x << 8;} if ((x >> 28) == 0) {n = n + 4; x = x << 4;} if ((x >> 30) == 0) {n = n + 2; x = x << 2;} n = n - (x >> 31);+ e; v; l( P5 ^/ U# I' j6 e4 o return n; }- @4 l' x% E6 S/ o% L6 a
将 x 的第 n 位置1,可以通过 x |= (x << n) 来实现 set_bit(char x, int n);将 x 的第 n 位清0,可以通过 x &= ~(1 << n) 来实现 clr_bit(char x, int n);- ?; G. k7 F9 J取出 x 的第 n 位的值,可以通过 (x >> n) & 1 来实现 get_bit(char x, int n);1 H, `6 ?( S$ ?* F8 ^1 h9 g7 V7 J如下: #define clr_bit(x, n) ( (x) &= ~(1 << (n)) )( \6 X c$ a6 l6 a* ?#define set_bit(x, n) ( (x) |= (1 << (n)) ) #define get_bit(x, n) ( ((x)>>(n)) & 1 ) 综合应用 以下仅列出,感兴趣可以参考下面链接. 关于操作计数方法 计算整数的符号 检测两个整数是否具有相反的符号 计算无分支的整数绝对值(abs) 计算两个整数的最小值(最小值)或最大值(最大值),而无需分支 确定整数是否为2的幂 标志延伸
有条件地否定一个值而不分支 根据掩码合并两个值中的位 计数位设置
计算奇偶校验(如果设置了奇数位数,则为1,否则为0)
交换价值
反转位序列
模数除法(又名计算余数)
查找整数的整数对数2(又称最高位集的位置)
查找整数的对数以10为底的整数 查找整数的整数对数10 查找32位IEEE浮点数的整数对数基数2 查找32位IEEE浮点的pow(2,r)根的整数对数基数2(对于无符号整数r) 计算连续的尾随零位(或查找位索引)
通过浮法舍入到2的下一个最高幂 向上舍入到2的下一个最高幂 交织位(也称为计算莫顿数)
测试单词中的字节范围(并计算出现的次数)
按词典顺序计算下一位排列 |
微信公众号
手机版