C语言复习2之位操作

位操作

位操作是程序设计中对位模式按位或二进制数的一元和二元操作. 在许多古老的微处理器上, 位运算

比加减运算略快, 通常位运算比乘除法运算要快很多. 在现代架构中, 情况并非如此:位运算的运算速度通常

与加法运算相同(仍然快于乘法运算)。

位运算符

取反(~)是一元运算符, 对一个二进制数的每一位执行逻辑反操作。使数字1成为0, 0成为1。

按位或(|) 处理两个长度相同的二进制数,两个相应的二进位中只要有一个为1,该位的结果值为1。

 按位异或(^)是对等长二进制模式按位或二进制数的每一位执行逻辑异按位或操作,操作的结果是如果某位不同则该位为1,否则该位为0。

按位与(&)处理两个长度相同的二进制数,两个相应的二进位都为1,该位的结果值才为1,否则为0。

移位

移位是一个二元运算符,用来将一个二进制数中的每一位全部都向一个方向移动指定位,溢出的部分将被舍弃,而空缺的部分填入一定的值。在类C语言中,左移使用两个小于符号"<<"表示,右移使用两个大于符号">>"表示。

逻辑移位(不管是左移位还是右移位) 都是空缺处补0。

算术移位  要保证符号位的不改变(逻辑左移位补0, 逻辑右移位看符号位)。

例如:110110011是-10110011前面的第一个1是符号位

那么110110011右移一位应该是111011001。

下面是一些位运算的简单编程题

  1. 不用额外变量交换两个整数的值
#include<iostream>
using namespace std;

int fun1(int a,int b)
{
        int tmp=a-b;
        tmp>>=(sizeof(int)*4-1);
        if(tmp)
                return b;
        return a;
}
int main()
{
        int a=-134,b=98;
        cout<<"max:"<<fun1(a,b)<<endl;
        return 0;
}

2. 不用任何比较判断找出两个数中较大的数

#include<iostream>
using namespace std;

void fun2(int &a,int &b)
{
        a=a+b;
        b=a-b;
        a=a-b;
}
int main()
{
        int a=-134,b=98;
        fun2(a,b);
        cout<<"a:"<<a<<", b:"<<b<<endl;
        return 0;
}

3. 整数的二进制表达式中的1的个数

#include<iostream>
using namespace std;

int fun3(int a)
{
        int tmp,count=0;
        for(int i=1;i<32;a>>=1,++i)
        {
                if(a&1==1)
                        count++;
        }
        return count;
}
int main()
{        fun4();
        cout<<fun3(a)<<endl;
        return 0;
}

4. 给定一个整数数组ar, 其中只有一个数出现了奇数次数,其他的数都是偶数词,打印这个数。

#include<iostream>
using namespace std;

int fun4(int *ar,int n)
{
        int tmp=0;
        for(int i=0;i<n;++i)
                tmp^=ar[i];
        return tmp;
}
int main()
{
        int ar[]={1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,2};
        int n=sizeof(ar)/sizeof(int);
        cout<<"value is :"<<fun4(ar,n)<<endl;
        return 0;
}
时间: 2024-10-11 22:00:08

C语言复习2之位操作的相关文章

c语言中的位移位操作

先要了解一下C语言里全部的位运算都是指二进制数的位运算.即使输入的是十进制的数,在内存中也是存储为二进制形式. “<<”使用方法: 格式是:a<<m,a和m必须是整型表达式,要求m>=0. 功能:将整型数a按二进制位向左移动m位,高位移出后,低位补0. “>>”使用方法: 格式是:a>>m,a和m必须是整型表达式,要求m>=0. 功能:将整型数a按二进制位向右移动m位,低位移出后,高位补0 C语言中的移位操作,内容不多.只是有些地方你不注意,就疏

关于c语言中负数位移位操作的漫谈

最近有个朋友在程序中使用了对16进制数做负数移位(编译器是gcc),本人最次产生好奇,所以研究了一些. 对一个数做负数位移位的操作是不规范的,但是是可行的. 具体例子: char tmp = 0x10; tmp = tmp << -1; 大家猜猜结果是什么,有人猜是tmp左移-1位不就是右移1位吗?结果是0x01? 很遗憾,电脑和人脑是不一样的.结果是0 为什么呢?为了找出原因,本人进行了一些小小的测试,并做出了有依据的结果. 由于知道+0和-0的区别,所以,我首先将tmp <<

C语言复习(一)关键字

最近在学COCOS2Dx,刚刚开始写一个塔防游戏,因为第一次用VS2012,感觉还不太习惯. C语言的大部分内容也忘记了,因此做一个简要的复习. 1.关键字: auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef unsigne

cpp学习(二)C语言复习

接下来复习一下C语言部分,毕竟C++与C语言本自同根生,并且在汇编层面C与C++可以说完全相同.假如你没有C语言基础的话,可以先暂停去学习一下C语言,C语言可以看"C语言之父"谭浩强的<C语言程序设计>或者观看学堂在线的免费公开课,在此推荐清华大学的c++课程:http://www.xuetangx.com/courses/course-v1:TsinghuaX+00740043X_2015_T2+sp/courseware/a0f3bf5a4c044dfaaad68148

C语言复习3/6日

1.变量:变量代表一个有名字的.具有特定属性的一个存储单元.它用来存放数据,也就是存放变量的值.在程序运行期间,变量的值是可以改变的.变量必须先定义后使用.变量名和变量值是两个不同的概念.变量名实际上是以一个名字代表的一个存储地址.在对程序编译连接时由编译系统给每一个变量名分配对应的存储地址.从变量中取值,实际上是通过变量名找到对应的内存地址,从该存储单元中读取数据. 2.符号常量:用#define指令,指定用一个符号名称代表一个常量.如#define  PI  3.14 注意:符号常量不是变量

c语言复习 —— 数组

数组的产生:数据是一种存放数据的容器.所以:一个数组中里面的元素是同一种类型的. 一维数组: 1.定义: 类型 名称 [元素数量] 注意:元素数量必须是整数,c语言中没有对象这个概念,所以存放的都是基本的数据类型,而在oc中的数组中存放的是必须是对象. 在c99之前,元素数量必须子编译的时候定义下来,而c99之后,确实可以没有没有定义下来. eg: int[10];//表示定了10个元素的数组,为整数类型. 2.特点: 1)所有的元素都是具有相同的类型. 2)一旦创建,就不能够更改. 3)数组中

C语言复习3/9

1.C语言中定义数组的形式为:类型符  数组名[常量表达式],常量表达式中可以包括常量和符号常量,如"int a[3+5];"是合法的.不能包含变量,如"int a[n];"是不合法的.也就是说,C语言不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值.如果在被调用的函数(不包括主函数)中定义数组,其长度可以是变量或非常量表达式.如: void func(int n) { int a[2 * n]; //合法,n的值从实参传来 . . . }

C语言复习

函数里面不能嵌套函数  这两个的区别是什么呢 #define a int[10] 属于宏定义,在编译的时候只进行替换,而不进行类型检查:typedef int a[10]: 只不过给int型取个别名,在编译的时候会进行类型检查. typedef 类型 别名;                  类型别名    用这个 #define 名字 替换成的字符          宏定义   只是把一个你写的东西替换成另一种东西,比如#define Hello "hello",把Hello替换成&

C语言复习——指针 链表 与 文件操作

刚刚进入大二,准备开始学习C++,对大一所学的C语言一次练习,正好也是赶上老师布置的任务,用C语言写一个  销售管理系统  ,就尽可能的把所学的都用上,也就是结构,指针,文件操作,还有数据结构,本次加入了链表. 用两个函数 Load_LinkList() 和 Save_LinkList() 让链表与文件操作结合,除了打印函数,其他都是在内存中操作链表,这样写更有条理,在创建链表时没有采用书上的用一个中间变量引导,并插入到结点前面,而是直接在链表尾的next申请内存,便于理解,操作也方便. /*首