c语言中位运算符_位运算符的用法

c语言中位运算符_位运算符的用法C语言的运算符是一个很有意思的东西,运用起来可以解决很多麻烦的事,但是想要灵活应用也有一定的难度,总结一下c语言运算符的用法和一些常用技巧.一.C语言位运算符简介C语言的位运算符有六种,分别是:>>  右移运算符&   按位与运算符|   按位或运算符^   按位异或运算符~   按位取反运算符这些运算符都是对于基本数据类型的二进制位进行操作的,这

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

C语言的运算符是一个很有意思的东西,运用起来可以解决很多麻烦的事,但是想要灵活应用也有一定的难度,总结一下c语言运算符的用法和一些常用技巧.

一.C语言位运算符简介

C语言的位运算符有六种,分别是:

>>   右移运算符

<<   左移运算符

&   按位与运算符

|    按位或运算符

^    按位异或运算符

~    按位取反运算符

这些运算符都是对于基本数据类型的二进制位进行操作的,这里我们只讨论整型数据类型的位运算

二.各个运算符的具体使用

>> 右移运算符:将整数的二进制形式整体向右移动,移动过后左边缺的位的填充取决于编译器,可能是算术右移也可能是逻辑右移

<< 左移运算符:将整数的二进制形式整体向左移动,移动过后右边缺的位用0补全

逻辑右移:在位移的过程中,符号位左边可能移入新的位,移入的新位用0填充,则称为逻

辑移位

算术右移:在位移的过程中,符号位左边可能移入新的位,移入的新位由符号位决定,符号位为

1则移入的新位用1补充,符号位为0则用0补充,保持原数的正负不变,这样的移位

方式称为算术移位.

具体是逻辑右移还是算术右移取决于编译器(我使用的编译器为vs,为算术右移)

注意:没有逻辑左移和算术左移

例:

int a = 10;
int b = 20;
int c = -2;
int d = -25;
printf("%d\n",a>>1);
printf("%d\n",b<<2);
printf("%d\n",c<<2);
printf("%d\n",d>>3);
输出结果:
5
40
-8
-4

分析:

10       (28个0)1010

右移1位  0(28个0)101    =       5

在我刚刚接触位运算的时候我对d的位移结果很是不解

因为:

-25   二进制为  1(26个0)11001

位移后为         1111(26个0)11  结果怎么看都不是-4

实际上在计算机的位移运算中,正数和负数的运算都是使用补码的形式运算

正数的补码 = 正数的原码

负数的补码 = 负数的原码除符号位外按位取反 + 1;

负数的原码 = (负数的补码-1)再对除符号位之外按位取反

负数的存储实际上也是以负数的补码存储的

所以

-25  二进制为           1(26个0)11001

-25  在程序中为      1(26个1)00111

位移后为                1111(26个1)00

再换为二进制原码形式   1(26个0)00100     为  -4

 

& 按位与运算符  对两个操作数的二进制每一位进行,1&1=1,1&0=0,0&1=0,0&0=0

|  按位或运算符  对两个操作数的二进制每一位进行,1|1=1,1|0=1,0|1=1,0|0=0

例子程序:

int a = -1;
int b = 2;
int c = 4;
printf("%d\n",b & c );
printf("%d\n", b | c );
printf("%d\n",a & b );
printf("%d\n", a | b );
输出:
0
6
2
-1

正数就不再分析了

负数还是按补码的形式

-1   补码   1(29个1)11

2    补码   0(29个0)10

进行按位或运算为   1(30个1)1    转换为负数原码刚好为-1

进行按位与运算为   0(29个0)10   为2

^    按位异或运算符  对两个操作数的二进制数每一位进行1^1=0,0^1=1,1^0=1;0^0=1

~    取反运算符      对操作数的二进制每一位进行,取反1->0,0->1

这两种运算符也是基于补码进行运算的

三.位运算符的具体应用

打印一个数的二进制形式
void printBit(int a)
{
	int i = 31;
	while( i >= 0 )
	{
		printf("%d",a>>i & 1);
		i--;
	}
	printf("\n");
}
不使用临时变量实现两个数值交换
void swap(int *a,int *b)
{
	*a = (*a)^(*b);
	*b = (*a)^(*b);
	*a = (*a)^(*b);
}
取出a中的第n位
int getBit(int a, int n)
{
	return  a>>n & 1;
}
将a中的第n位设为0
void setBitZero(int *a,int n)
{
	(*a) = (*a) & ~(1<<n);
}
将a中的第n位设为1
void setBitOne(int *a,int n)
{
	(*a) = (*a) | (1<<n);
}
求a的相反数
a = ~a+1;

四.一个运用位运算符的ACM题

找球号(一)

时间限制:3000 ms  | 内存限制:65535 KB

难度:3

描述

在某一国度里流行着一种游戏。游戏规则为:在一堆球中,每个球上都有一个整数编号i(0<=i<=100000000),编号可重复,现在说一个随机整数k(0<=k<=100000100),判断编号为k的球是否在这堆球中(存在为“YES”,否则为“NO”),先答出者为胜。现在有一个人想玩玩这个游戏,但他又很懒。他希望你能帮助他取得胜利。

输入

第一行有两个整数mn(0<=n<=1000000<=m<=1000000)m表示这堆球里有m个球,n表示这个游戏进行n次。
接下来输入m+n个整数,前m个分别表示这m个球的编号i,后n个分别表示每次游戏中的随机整数k

输出

输出“YES”“NO”

样例输入

6 4

23 34 46 768 343 343

2 4 23 343

样例输出

NO

NO

YES

YES

这道题并不是一个难题,解法很多,由于数据量比较大,所以在求解的时间限制上很多种方法会超时,这道题虽然我做出来的,但是在运行时间上落后太多的,我使用的是c++ stl 中的set实现,用时2700+ms,内存也用的不少,下面贴一个比较好的方法:

#define MAXN 3125010
int vis[MAXN] = {0} ;
int main()
{
	int m , n , x ;
	int i ;
	scanf("%d%d", &m , &n ) ;
	for( i = 0 ; i < m ; ++i )
	{
		scanf("%d", &x ) ;
		vis[ x / 32 ] |= 1 << x % 32 ;
	}
	for( i = 0 ; i < n ; ++i )
	{
		scanf("%d", &x ) ;
		if( vis[ x / 32 ] & ( 1 << x % 32 ) )
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0 ;
}

使用了c语言的位运算符,在数组的一个内存空间中存储32个数字是否存在的信息,这样既节省下来了内存空间,也使得查找数字时候时间复杂度为O(1)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/185884.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java redis密码_Redis 密码设置和查看密码[通俗易懂]

    java redis密码_Redis 密码设置和查看密码[通俗易懂]redis没有实现访问控制这个功能,但是它提供了一个轻量级的认证方式,可以编辑redis.conf配置来启用认证。1、初始化Redis密码:在配置文件中有个参数:requirepass这个就是配置redis访问密码的参数;比如requirepasstest123;(Ps:需重启Redis才能生效)redis的查询速度是非常快的,外部用户一秒内可以尝试多大150K个密码;所以密码要尽量长(…

    2022年9月6日
    4
  • mysql跨库分页、分表为什么这么难?[通俗易懂]

    mysql跨库分页、分表为什么这么难?[通俗易懂]前言:当业务数据达到一定量级(比如:mysql单表记录量>1千万)后,通常会考虑“分库分表”将数据分散到不同的库或表中,这样可以大大提高读/写性能。但是问题来了,对于select*fromtablelimitoffset,pagesize这种分页方式,原来一条语句就可以简单搞定的事情会变得很复杂,本文将与大家一起探讨分库分表后”分页”面临的新问题。mysql跨库分页、分表为什么这么难?一、分表对分页的影响1.1分段法1.2模余均摊法二、全局法(limitx+y)2.1按分段

    2022年7月20日
    9
  • 机器学习 Lasso回归算法「建议收藏」

    机器学习 Lasso回归算法「建议收藏」Lasso回归算法:坐标轴下降法与最小角回归法小结    前面的文章对线性回归做了一个小结,文章在这:线性回归原理小结。里面对线程回归的正则化也做了一个初步的介绍。提到了线程回归的L2正则化-Ridge回归,以及线程回归的L1正则化-Lasso回归。但是对于Lasso回归的解法没有提及,本文是对该文的补充和扩展。以下都用矩阵法表示,如果对于矩阵分析不熟悉,推荐学习张贤达的《矩阵分析与应用》…

    2022年5月11日
    218
  • EXCEL countif函数多条件

    在MSEXCEL中,countif如果要满足多个条件怎么办呢?1、答案就是:使用条件集合{}和sum函数。即在countif()第二个参数中使用条件集合{},然后用sum()函数求满足这些条件的

    2021年12月26日
    242
  • Elasticsearch索引迁移的四种方式

    Elasticsearch索引迁移的四种方式本文主要讲解Elasticsearch下实现索引迁移的几种方式。0、引言将ES中的索引拷贝到其他ES中,或者将ES整体迁移,研究发现有两个开源的工具:elaticserch-dump和Elasticsearch-Exporter。除此之外,logstash在索引同步、迁移方面的作用也很大。两工具及logstash实现迁移的介绍、安装、使用、验证效果等展示如下:1、el…

    2022年5月29日
    110
  • ORACLE分页查询SQL语句(最有效的分页)

    ORACLE分页查询SQL语句(最有效的分页)**一、效率高的写法**1.无ORDERBY排序的写法。(效率最高)(经过测试,此方法成本最低,只嵌套一层,速度最快!即使查询的数据量再大,也几乎不受影响,速度依然!)SELECT*FROM(SELECTROWNUMASrowno,t.*FROMemptWHEREhire_dateBETWEENTO_DATE…

    2022年4月29日
    530

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号