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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • linux openssl制作ssl证书_openssl生成自签名证书 c++代码

    linux openssl制作ssl证书_openssl生成自签名证书 c++代码目录前言1概念2环境3创建根证书CA4颁发证书4.1在需要证书的服务器上,生成证书签署请求4.2在根证书服务器上,颁发证书5测试5.1读取test.pfx文件5.2读取test.cer文件前言最近,被分配了一个任务,完成数字证书管理系统的开发,一开始我是一脸懵逼的,因为以前我对于什么数字证书都没了解过,可谓了一片空白,也不知其是用来…

    2022年9月19日
    2
  • ribbon的负载均衡策略_f5负载均衡配置

    ribbon的负载均衡策略_f5负载均衡配置在这里吐槽一句:网上很多文章真是神坑,你不看还好,看了只会问题越来越多,就连之前的问题都没有解决!!!不多说了,Ribbon作为后端负载均衡器,比Nginx更注重的是请求分发而不是承担并发,可以直接感知后台动态变化来指定分发策略。它一共提供了7种负载均衡策略:策略名策略声明策略描述实现说明

    2022年10月13日
    2
  • webservice接口与HTTP接口的使用以及区别

    webservice接口与HTTP接口的使用以及区别一、webservice的概念Web是使应用程序可以与平台和编程语言无关的方式进行相互通信的一项技术。Web服务是一个软件接口,它描述了一组可以在网络上通过标准化的XML消息传递访问的操作。它使用基于XML语言的协议来描述要执行的操作或者要与另一个Web服务交换的数据。一组以这种方式交互的Web服务在面向服务的体系结构(Service-OrientedArchitectu…

    2022年5月18日
    48
  • Odin Inspector 系列教程 — Hide Reference Object Picker Attribute[通俗易懂]

    Odin Inspector 系列教程 — Hide Reference Object Picker Attribute[通俗易懂]HideReferenceObjectPickerAttribute特性:隐藏非Unity序列化引用类型属性上方显示的多态对象选择器。usingSirenix.OdinInspector;usingSystem.Collections.Generic;usingUnityEngine;publicclassHideReferenceO…

    2022年7月21日
    10
  • ORA-12514 解决方法

    ORA-12514 解决方法场景:修改oracle系统参数之后,数据库重启,客户端报ORA-12514错误,其实这只是表象,实际并非Listener的问题。SELECT*FROMV$RESOURCE_LIMIT根据

    2022年7月1日
    29
  • .Net审计之.Net Json反序列化

    .Net审计之.NetJson反序列化前言偶然下遇到一个.NET下有意思的Json反序列化点,记录一下反序列化内容,直入主题。.NetJson常见序列化与反序列化NET中常见的数据格

    2021年12月13日
    53

发表回复

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

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