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

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

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

循环移位的概念:

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

掩码的概念:

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

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

 #include <stdio.h>
#pragma warning (disable:4996) void itobs(int var);
void mask1(int *mask);
void mask2(int *mask);
void mask3(int *mask); int main(void)
{
int mask = ;
mask1(&mask);
mask = ;
mask2(&mask);
mask = ;
mask3(&mask); return ;
}
void mask1(int *mask)
{
*mask = ( << ) | ( << ) | ( << ) | ( << );
//这样可以生成前面28个0,后面四个1的一个掩码
itobs(*mask);
printf("\n"); }
void mask2(int *mask)
{
int n = ;//表示要生成连续四个1的掩码,和mask1()方法结果一样
while (n--){
*mask |= << n;
}
itobs(*mask);
printf("\n");
}
void mask3(int *mask)
{
int i = ;
for (i = ; i > ; i--){//可以用来生成固定位置是1的掩码
*mask |= << i;
}
itobs(*mask);
printf("\n");
}
//利用位运算将整数转化为二进制表示
void itobs(int var)
{
int i = ;//整数在内存中占4个字节,也就是32位
/*每次生成一个只有一位是1,其他位置是0的掩码和目标数按位与,
就可以得到目标数的这个位置是0还是1,然后输出0或1就是目标数对应的二进制表示
*/
while (i--){
if (var & << i)
printf("%d", );
else
printf("%d", );
if (i % == )//每八个分割显示,看起来比较好
printf(" ");
}
}

循环移位操作:

 #include <stdio.h>
void circleMove(int *pdata, int n);
void itobs(int var);
int main(void)
{
int data=;
// printf("请输入一个数字:\n");
// scanf("%d",&data);
itobs(data);
printf("\n");
//将7循环右移两位
circleMove(&data, -);
itobs(data); return ;
}
//循环移位,当n>0的时候,当n<0的时候右移
//循环移位,就是把按理说移出去的那些补到另一头
void circleMove(int *pdata, int n)
{
unsigned int data=*pdata;//使用unsigned处理,则发生右移后空出来的位置是统一补0的
int temp=;
if(n>)
temp=n;
else
temp=-n;
int mask=;//掩码,被移调多少位,就要生成几位是1的掩码
//这个while循环用来生成掩码
while(temp--)
mask |=<<temp;
if(n>){//左移
data = data<<n | (data>>(sizeof(data)*-n)&mask);
//前半部分处理左移,后半部分将本该移出去的先右移,用掩码保存起来,然后前后或就的到循环移位的数
}
else if(n<){//右移
temp=-n;
data = data>>temp | ((mask&data)<<(sizeof(data)*-temp));
}
*pdata=data;
}
void itobs(int var)
{
int i=;
while(i--){
if(var&<<i)
printf("%d",);
else
printf("%d",);
if(i%==)
printf(" ");
} }

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

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

 #include <stdio.h>
void swap(int *a, int *b);
void judgePower(int *num);
int main(void)
{
int a=,b=;
swap(&a,&b);
printf("a=%d b=%d\n",a,b); int num=;
scanf("%d",&num);
judgePower(&num); return ;
}
//用按位异或交换两个数的值,值针对整型和字符型
void swap(int *a, int *b)
{
*a =*a^*b;
*b =*a^*b;
*a =*a^*b;
}
//判断一个数是不是2的幂
void judgePower(int *num)
{
/*
原理:例如8的二进制表示是1000,它是2的幂,8-1=7=0111
(1000)&(0111)=0所以,8是2的幂
*/
if((*num)&(*num-))
printf("no");
else
printf("yes");
}

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

 #include <stdio.h>
#include <string.h>
#pragma warning(disable:4996)
void encrpty(char *secret, char key);//密钥为单个字符时的异或加密方法
void de_encrpty(char *secret, char key);//密钥为单个字符时的异或解密方法
void encrptyStr(char *secret, char *key);//密钥为字符串时的异或加密方法
void de_encrptyStr(char *secret, char *key);//密钥为字符串时的异或解密方法
void encode(char *secret);//对字符串进行循环移位加密
void decode(char *secret);//对字符串进行循环移位解密
int main(void)
{
char source[] = { };
printf("请输入需要加密的字符:\n");
gets(source);
//密钥为单个字符时的异或加密方法
encrpty(source, 'o');
printf("\n密钥为单个字符时加密后:\n%s\n", source);
//密钥为单个字符时解密
de_encrpty(source, 'o');
printf("\n密钥为单个字符时解密后:\n%s\n", source);
//密钥为字符串时加密,此处内置使用“love”字符串加密
encrptyStr(source, "love");
printf("\n密钥为字符串时加密后:\n%s\n", source);
//密钥为字符串时解密
de_encrptyStr(source, "love");
printf("\n密钥为字符串时解密后:\n%s\n", source);
//进行循环移位加密后
encode(source);
printf("\n进行循环移位加密后:\n%s\n", source);
//进行循环移位解密后
decode(source);
printf("\n进行循环移位解密后:\n%s\n", source);
return ;
}
//秘钥是单个字符的加密方法
void encrpty(char *secret, char key)
{
while (*secret)
{
if (*secret == key)
/*当字符串中字符和密钥相同时跳过,避免数据截断
由于相同字符异或结果为0,放在字符串中就结束了字符串
*/
secret++;
else{
*secret ^= key;//与密钥异或
secret++;
}
}
}
void de_encrpty(char *secret, char key)
{
while (*secret)
{
if (*secret == key)
secret++;
else{
*secret ^= key;//用异或来加密,自然用异或解密
secret++;
}
}
}
//密钥是一个字符串的加密方法
void encrptyStr(char *secret, char *key)
{
int klen = strlen(key);//密钥的长度
int i = ;//访问密钥的循环变量
while (*secret != '\0')
{
if (*secret == key[i]){//若字符和密钥相同,则跳过,避免数据截断
secret++;
i++;
}
else{
*secret ^= key[i];
secret++;//向后推移目标串
i++;//向后推移密钥串
}
if (i%klen == )//当密钥串遍历到头时,就把访问变量重置为0,从第一位重新开始
i = ;
}
}
//密钥是一个字符串的解密方法,原理同加密
void de_encrptyStr(char *secret, char *key)
{
int klen = strlen(key);
int i = ;
while (*secret)
{
if (*secret == key[i]){
secret++;
i++;
}
else{
*secret ^= key[i];
secret++;
i++;
}
if (i%klen == )
i = ;
}
}
/*对字符串进行循环移位加密,这个不需要秘钥
原理是对每一个字符进行循环移位加密,例如字符的二进制形式是1000 0001,
则向右循环移位一位时的得到的结果是1100 0000
*/
void encode(char *secret)
{
unsigned char temp = ;
while (*secret)
{
temp = *secret;
temp = (temp & ) << | temp >> ;
//这里使用向右循环移动一位的方式,也可以是别的位数
*secret = temp;
secret++;
}
}
//对字符串进行循环移位加密,是加密的逆过程
void decode(char *secret)
{
unsigned char temp = ;
while (*secret)
{
temp = *secret;
temp = (temp&( << )) >> | temp << ;
*secret = temp;
secret++;
}
}

C语言 位操作的更多相关文章

  1. C语言位操作初步

    位操作允许程序员对单独的位进行操作,例如,早某些机器上,短整型占16位,位操作将每一位单独操作. 位操作允许程序员设置.清除.测试与其他的操作,这些操作如下表: 操作 含义 & 按位与 | 按 ...

  2. 原码、反码、补码及位操作符,C语言位操作

    计算机中的所有数据均是以二进制形式存储和处理的.所谓位操作就是直接把计算机中的二进制数进行操作,无须进行数据形式的转换,故处理速度较快. 1.原码.反码和补码 位(bit) 是计算机中处理数据的最小单 ...

  3. 嵌入式、C语言位操作的一些技巧汇总

    下面分享关于位操作的一些笔记: 一.位操作简单介绍 首先,以下是按位运算符: 在嵌入式编程中,常常需要对一些寄存器进行配置,有的情况下需要改变一个字节中的某一位或者几位,但是又不想改变其它位原有的值, ...

  4. C语言位操作的算法

    1.头文件 #ifndef _INC_BITOPERATION #define _INC_BITOPERATION #endif /* 封装了所有的位操作运算 */ #include<stdio ...

  5. C语言位操作(转)

    http://www.cnblogs.com/cpoint/category/524132.html  

  6. C语言位操作

    #include <stdio.h> void print(int); int main(void) { int flag = 0xffe4; print(flag); printf(&q ...

  7. C语言位操作--逻辑运算符组合

    假设读者熟悉普通代数与布尔代数,下面是部分常见的涉及到加法.减法与逻辑运算符的组合: a.        -x=~x+1 b.           =~(x-1) c.        ~x=-x-1 ...

  8. C语言位操作--奇偶校验算法

    信息是以比特流的方式传输的,类似01000001.在传输过程中,有可能会发生错误,比如,我们存储了01000001,但是取出来却是01000000,即低位由0变成了1.为了检测到这种错误,我们可以通过 ...

  9. C语言位操作--不用中间变量交换两数值

    1.使用加法与减法交换两数值: #define SWAP(a, b) ((&(a) == &(b)) || \ (((a) -= (b)), ((b) += (a)), ((a) = ...

随机推荐

  1. UVa11248 Frequency Hopping(最大流+最小割)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=33206 [思路] 最大流最小割. 可以确定的是如果不可行需要修改的 ...

  2. VB.net 连接池

    上篇博客介绍了临时表的使用,以及它的生命周期和连接池的关系.那么为了能更好的把握临时表的产生和消亡,本篇博客就介绍Vb.net连接池.在打开和关闭数据库连接时的耗费的资源是非常高的.那么在程序需要频繁 ...

  3. 【repost】如何学好编程 (精挑细选编程教程,帮助现在在校学生学好编程,让你门找到编程的方向)四个方法总有一个学好编程的方法适合你

    方法(一)编了这么久的程序,一直想找机会总结下其中的心得和方法,但回想我这段编程道路,又很难说清楚,如果按照我走过的所有路来说,显然是不可能的!当我看完了云风的<游戏之旅--编程感悟>和梁 ...

  4. java_method_Log输出日志的方法

    package cn.com.qmhd.tools; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigura ...

  5. JAX-WS + Spring 开发webservice

    通过几天的时间研究了下使用jax-ws来开发webservice,看了网上的一些资料总结出jax-ws的开发大概分为两种. 以下项目使用的spring3.0,jar包可以到官网下载 第一种:使用独立的 ...

  6. POJ1184-------操作分离的BFS

    题目地址:http://poj.org/problem?id=1184 题目意思: 给你两个6位数,一个是起始值,一个最终值 初始光标在最左边 你可以左移或者右移光变 在光标处+1或者-1 在光标处和 ...

  7. 设计模式----代理模式(Proxy)

    为还有一个对象提供一个替身或占位符以控制对这个对象的訪问. 代理模式的组成: 主题接口(Subject):提取真正主题与代理的公共方法,让使用真正主题的地方也能用代理取代. 真正主题(RealSubj ...

  8. [Rails Level 2] Ground up

    1. Rails commends line: Example: rails new blog --skip-test-unit --database=postgresql

  9. 蓝牙(BLE)应用框架接口设计和应用开发——以TI CC2541为例

    本文从功能需求的角度分析一般蓝牙BLE单芯片的应用框架(SDK Framework)的接口设计过程,并以TI CC2541为例说明BLE的应用开发方法. 一.应用框架(Framework) 我们熟知的 ...

  10. 解决Win8不能上网攻略第二版!三步秒杀原驱动

    关于Win8消费者预览版的网卡驱动确实是令人头疼的事情,不少用户都抱怨无法联网而且驱动卸载十分麻烦.IT之家社区luoyousi 此前分享<图文教程:解决Win8消费者预览版不能上网问题> ...