C语言 位操作

c语言位操作中需要注意有:

  1. 位操作只针对整型和字符型数据

  2. 在右移操作中:对无符号数和有符号中的正数补 0;符号数中的负数,取决于所使用的系统:补 0 的称为“逻辑右移”,补 1 的称为“算术右移”。

循环移位的概念:

循环移位就是把从左边移出去的,补到右边去,或者从右边移出去的补到左边去,例如1000 0001循环右移以为得到:1100 0000,循环左移一位得到0000 0011

掩码的概念:

掩码就是掩盖住你不想让它出现的部分,例如在网络中的子网掩码,就是将网络中的子网内部IP划分屏蔽掉,例如需要判断两个IP是不是同一个网段的,就把它们分别和本网断的子网掩码换算成二进制,按位相与,得到要是同一个值就证明两个是同一个网段的。

生成掩码的三种方式和整数转化成二进制:

 1 #include <stdio.h>
 2 #pragma warning (disable:4996)
 3 
 4 void itobs(int var);
 5 void mask1(int *mask);
 6 void mask2(int *mask);
 7 void mask3(int *mask);
 8 
 9 int main(void)
10 {
11     int mask = 0;
12     mask1(&mask);
13     mask = 0;
14     mask2(&mask);
15     mask = 0;
16     mask3(&mask);
17 
18     return 0;
19 }
20 void mask1(int *mask)
21 {
22     *mask = (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
23     //这样可以生成前面28个0,后面四个1的一个掩码
24     itobs(*mask);
25     printf("\n");
26 
27 }
28 void mask2(int *mask)
29 {
30     int n = 4;//表示要生成连续四个1的掩码,和mask1()方法结果一样
31     while (n--){
32         *mask |= 1 << n;
33     }
34     itobs(*mask);
35     printf("\n");
36 }
37 void mask3(int *mask)
38 {
39     int i = 0;
40     for (i = 6; i > 2; i--){//可以用来生成固定位置是1的掩码
41         *mask |= 1 << i;
42     }
43     itobs(*mask);
44     printf("\n");
45 }
46 //利用位运算将整数转化为二进制表示
47 void itobs(int var)
48 {
49     int i = 32;//整数在内存中占4个字节,也就是32位
50     /*每次生成一个只有一位是1,其他位置是0的掩码和目标数按位与,
51     就可以得到目标数的这个位置是0还是1,然后输出0或1就是目标数对应的二进制表示
52     */
53     while (i--){
54         if (var & 1 << i)
55             printf("%d", 1);
56         else
57             printf("%d", 0);
58         if (i % 8 == 0)//每八个分割显示,看起来比较好
59             printf(" ");
60     }
61 }

循环移位操作:

 1 #include <stdio.h>
 2 void circleMove(int *pdata, int n);
 3 void itobs(int var);
 4 int main(void)
 5 {
 6     int data=7;
 7 //    printf("请输入一个数字:\n");
 8 //    scanf("%d",&data);
 9     itobs(data);
10     printf("\n");
11     //将7循环右移两位
12     circleMove(&data,  -2);
13     itobs(data);
14 
15     return 0;
16 }
17 //循环移位,当n>0的时候,当n<0的时候右移
18 //循环移位,就是把按理说移出去的那些补到另一头
19 void circleMove(int *pdata, int n)
20 {
21     unsigned int data=*pdata;//使用unsigned处理,则发生右移后空出来的位置是统一补0的
22     int temp=0;
23     if(n>0)
24         temp=n;
25     else
26         temp=-n;
27     int mask=0;//掩码,被移调多少位,就要生成几位是1的掩码
28     //这个while循环用来生成掩码
29     while(temp--)
30         mask |=1<<temp;
31     if(n>0){//左移
32         data = data<<n | (data>>(sizeof(data)*8-n)&mask);
33         //前半部分处理左移,后半部分将本该移出去的先右移,用掩码保存起来,然后前后或就的到循环移位的数
34     }
35     else if(n<0){//右移
36         temp=-n;
37         data = data>>temp | ((mask&data)<<(sizeof(data)*8-temp));
38     }
39     *pdata=data;
40 }
41 void itobs(int var)
42 {
43     int i=32;
44     while(i--){
45         if(var&1<<i)
46             printf("%d",1);
47         else
48             printf("%d",0);
49         if(i%8==0)
50             printf(" ");
51     }
52 
53 }

利用位运算实现两个数交换值,不引入第三方变量和判断一个数是不是2的幂,也可以直接简单的使用加法,例如:

a=5,b=3;    a=a+b;    b=a-b;    a=a-b;但是着用方法存在溢出的危险,所以使用下列方法比较好

 1 #include <stdio.h>
 2 void swap(int *a, int *b);
 3 void judgePower(int *num);
 4 int main(void)
 5 {
 6     int a=5,b=3;
 7     swap(&a,&b);
 8     printf("a=%d b=%d\n",a,b);
 9 
10     int num=0;
11     scanf("%d",&num);
12     judgePower(&num);
13 
14     return 0;
15 }
16 //用按位异或交换两个数的值,值针对整型和字符型
17 void swap(int *a, int *b)
18 {
19     *a =*a^*b;
20     *b =*a^*b;
21     *a =*a^*b;
22 }
23 //判断一个数是不是2的幂
24 void judgePower(int *num)
25 {
26     /*
27         原理:例如8的二进制表示是1000,它是2的幂,8-1=7=0111
28         (1000)&(0111)=0所以,8是2的幂
29     */
30     if((*num)&(*num-1))
31         printf("no");
32     else
33         printf("yes");
34 }

字符文件的 单个字符密钥异或加密、字符串密钥异或加密、循环移位加密:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #pragma warning(disable:4996)
  4 void encrpty(char *secret, char key);//密钥为单个字符时的异或加密方法
  5 void de_encrpty(char *secret, char key);//密钥为单个字符时的异或解密方法
  6 void encrptyStr(char *secret, char *key);//密钥为字符串时的异或加密方法
  7 void de_encrptyStr(char *secret, char *key);//密钥为字符串时的异或解密方法
  8 void encode(char *secret);//对字符串进行循环移位加密
  9 void decode(char *secret);//对字符串进行循环移位解密
 10 int main(void)
 11 {
 12     char source[100] = { 0 };
 13     printf("请输入需要加密的字符:\n");
 14     gets(source);
 15     //密钥为单个字符时的异或加密方法
 16     encrpty(source, 'o');
 17     printf("\n密钥为单个字符时加密后:\n%s\n", source);
 18     //密钥为单个字符时解密
 19     de_encrpty(source, 'o');
 20     printf("\n密钥为单个字符时解密后:\n%s\n", source);
 21     //密钥为字符串时加密,此处内置使用“love”字符串加密
 22     encrptyStr(source, "love");
 23     printf("\n密钥为字符串时加密后:\n%s\n", source);
 24     //密钥为字符串时解密
 25     de_encrptyStr(source, "love");
 26     printf("\n密钥为字符串时解密后:\n%s\n", source);
 27     //进行循环移位加密后
 28     encode(source);
 29     printf("\n进行循环移位加密后:\n%s\n", source);
 30     //进行循环移位解密后
 31     decode(source);
 32     printf("\n进行循环移位解密后:\n%s\n", source);
 33     return 0;
 34 }
 35 //秘钥是单个字符的加密方法
 36 void encrpty(char *secret, char key)
 37 {
 38     while (*secret)
 39     {
 40         if (*secret == key)
 41             /*当字符串中字符和密钥相同时跳过,避免数据截断
 42               由于相同字符异或结果为0,放在字符串中就结束了字符串
 43             */
 44             secret++;
 45         else{
 46             *secret ^= key;//与密钥异或
 47             secret++;
 48         }
 49     }
 50 }
 51 void de_encrpty(char *secret, char key)
 52 {
 53     while (*secret)
 54     {
 55         if (*secret == key)
 56             secret++;
 57         else{
 58             *secret ^= key;//用异或来加密,自然用异或解密
 59             secret++;
 60         }
 61     }
 62 }
 63 //密钥是一个字符串的加密方法
 64 void encrptyStr(char *secret, char *key)
 65 {
 66     int klen = strlen(key);//密钥的长度
 67     int i = 0;//访问密钥的循环变量
 68     while (*secret != '\0')
 69     {
 70         if (*secret == key[i]){//若字符和密钥相同,则跳过,避免数据截断
 71             secret++;
 72             i++;
 73         }
 74         else{
 75             *secret ^= key[i];
 76             secret++;//向后推移目标串
 77             i++;//向后推移密钥串
 78         }
 79         if (i%klen == 0)//当密钥串遍历到头时,就把访问变量重置为0,从第一位重新开始
 80             i = 0;
 81     }
 82 }
 83 //密钥是一个字符串的解密方法,原理同加密
 84 void de_encrptyStr(char *secret, char *key)
 85 {
 86     int klen = strlen(key);
 87     int i = 0;
 88     while (*secret)
 89     {
 90         if (*secret == key[i]){
 91             secret++;
 92             i++;
 93         }
 94         else{
 95             *secret ^= key[i];
 96             secret++;
 97             i++;
 98         }
 99         if (i%klen == 0)
100             i = 0;
101     }
102 }
103 /*对字符串进行循环移位加密,这个不需要秘钥
104 原理是对每一个字符进行循环移位加密,例如字符的二进制形式是1000 0001,
105 则向右循环移位一位时的得到的结果是1100 0000
106 */
107 void encode(char *secret)
108 {
109     unsigned char temp = 0;
110     while (*secret)
111     {
112         temp = *secret;
113         temp = (temp & 1) << 7 | temp >> 1;
114         //这里使用向右循环移动一位的方式,也可以是别的位数
115         *secret = temp;
116         secret++;
117     }
118 }
119 //对字符串进行循环移位加密,是加密的逆过程
120 void decode(char *secret)
121 {
122     unsigned char temp = 0;
123     while (*secret)
124     {
125         temp = *secret;
126         temp = (temp&(1 << 7)) >> 7 | temp << 1;
127         *secret = temp;
128         secret++;
129     }
130 }

 

posted @ 2015-08-23 15:01  luo__jialin  阅读(342)  评论(0编辑  收藏  举报