C:操作符小结

操作符就像C语言的骨骼,将数据联系在一起,得以完成工作,今天我们就来分门别类地总结一下:


1.算数操作符
+    -    *     /   %

加法,减法,乘法,与数学中的形式和运算方法没有区别,这里只提一下除法运算符和取余操作符:

  • 余运算符%两边必须为整数,返回整除之后的余数,而其余操作符都可以进行整书/浮点书运算
  • 任意一端出现浮点数,返回结果便为浮点数;当都为整数时,返回是整除后的数;(切记不可四舍五入,这个表达式就是要直接丢失小数位的值)
2.移位操作符
<<       >>

左移操作符记住左边丢失,右边补零,右移操作符则根据编译器分为算术右移和逻辑右移,算术右移是右边丢失,左边用符号位填充,逻辑右移则是左边补零;右移一位相当于给原数据除2,在求平均值时,这不失为一个好办法;
不要小看这两个操作符,有些事情用它们才能办的简单轻松,我们来看下面这个例子:

写一个函数返回参数2进制中1的个数;函数原型int count_one_bits(unsigned int value)_

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
int count_one_bits(const unsigned int value)
{
	int i = 32;
	int count = 0;
	while (i--)
	{
		count += (value >> i) % 2;
	}
	return count;
}

int main()
{
	unsigned int num = 0;
	int value = 0;
	printf("请输入你期望的数:>\n");
	scanf("%u", &num);
	value = count_one_bits(num);
	printf("二进制中1的个数为:>%d\n", value);
	system("pause");
	return 0;
}

思路:当整形数据右移时,我们知道是从左边补符号位,而无符号整型数据右移时,是从左边补零,当需要判断value时只需要向右移动位数然后模2便可以判断这一位是不是1;然后计数器加一,就可以实现目的
在这里插入图片描述

3.位操作符
&     ^     |

从左到右一次分别是按位与,按位异或,和按位或,这里主要把不太常用的异或
拎出来瞧瞧,先来看一道问题:

不能创建第三个变量,实现两个数的交换
吔?是不是一时间摸不着头脑?看看异或是怎么发挥作用的吧

#include<stdio.h>
int main()
{
   int a = 10;
   int b =20;
   a = a^b;
   b = a^b;
   a = a^b;
   printf("a = %d,b = %d",a,b);
   return 0;
}

程序这个地方一走,我们看到的确是改变了:
在这里插入图片描述
第一次a=a^b这个操作,我们可以比作a和b的数据揉在一起,存在a里;
然后b=a^b,时这里的a已经是a和b一起的数据了,异或b时b就像一个密码,解读出了a原来的值;
第二次a=a^b时,b里面存放的是原来的a,这时作为密码又解读出了b;这样就实现了要求;
注意:这其实只是比较偏门的用法,代码效率很差,所以当没有人要求时,我们还是创建第三变量来交换数据吧o_0.
再来看一道:
有一组数据,除一个数之外其他书都是成对出现的,请找出这个数:


#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int FindSingle(int *arr,int sz)
{
	int i = 0;
	int single =arr[0];
	for (i = 0; i < (sz-1); i ++)
	{
		single ^= arr[i + 1];
	}
	return single;
}

int main()
{
	int arr[] = {1,3,2,4,6,5,8,7,9,3,1,2,4,8,7,6,9};
	int sz = sizeof(arr)/sizeof(arr[0]);
	printf("%d\n", FindSingle(arr,sz));
	system("pause");
	return 0;
}

程序跑起来,我们看到它立刻就找到那个"单身狗",是不是很神奇呢?:
在这里插入图片描述
这是因为按位异或符将数据"加密"存储起来时,再遇到相同于已“加密”的元素的数加入时,就会将这两个元素从这一团密码中剔除出去(相同为零嘛),所以别看糅合了这么多的数,随着对应成对的数不断加入,异或结果就会越来越“纯净”,最终只剩下了那个“signel”;
ps:在人群中如此显眼的单身果然伤不起啊=_=||

4.赋值操作符&复合赋值操作符
 = += -= *= /= %= >>= <<= &= |= ^=

第一个大家都不陌生吧,给变量赋值就是它了,那后面的呢?,其实都可以用下面这种形式来理解:

int a = 0;
a+= 1;
a=a+1;

这两个式子效果是一样的,也同样可以类比到其他复合赋值操作符上.
好,我们牛刀小试一番:
编写函数:unsigned int reverse_bit(unsigned int value);这个函数的返回值是参数value的二进制位模式从左到右翻转后的值;
先来看看题目的要求:得到翻转后的值,那就是说原来在第一位的数就要跑到最末位这样一一对应,函数传入和返回都是无符号整形,那么说明我们不用考虑操作符号位会对数据和结果产生偏差,放心大胆的使用左右移吧,假设我要看value的二进制形式第2低位是不是1,我就可以先把它右移一位,然后和1按位于,嗯,得到的结果确定是1,这是我在将返回值按位或一个左移30位的1,这样把value的32位统统检查一遍,就可以达成要求;
来看看具体如何实现吧:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

unsigned int reverse_bit(unsigned int value)
{
	int i = 0;
	unsigned int reversed = 0;
	while (i<sizeof(value) * 8)
	{
		if (((value >> i) &1)== 1)
		{
			reversed |= 1 << (sizeof(value) * 8-(i+1));
		}
		i++;
	}
	return reversed;
}

int main()
{
	unsigned int value = 0;
	printf("请输入你想要反转的值:>\n");
	scanf("%u", &value);
	printf("翻转后的值:>%u\n", reverse_bit(value));
	system("pause");
	return 0;
}

在这里插入图片描述
输入25(0000000000000000000000000011001),对应的值应该是2550136832(10011000000000000000000000000000),嗯,没问题,你的结果呢?

5.单目操作符

单目操作符便指的是只需要一个操作数的操作符号:

!逻辑反操作 -负值 +正值 &取地址 sizeof 求操作数类型长度 ~按位取反 --前/后置--
++前/后置加价 *解引用  (type)强制类型转换 
6.关系操作符
> <  >= <= == !=
7.逻辑操作符
&&    ||

大名鼎鼎的’短路’逻辑与和’短路’逻辑或啊,不知道多少英雄好汉不留神就被他坑了
来看下面这道题:
求输出结果

#include<stdio.h>
int main ()
{
  int i1 = 0,i2 = 0,a = 0,b =2, c= 3,d =4;
  i1 = a++ && ++b && d++;
  //i2 = a++||++b||d++;
  printf("a = %d\n b = %d\n  c = %d\n d =%d\n",a,b,c,d);
  return 0;
}

说实话,我在没了解这两个操作符的威名前,看到这个题,总感觉有问题,但就是说不上来在哪…
我们来详细分析一下:
首先说说为什么要给他们的名字前面加‘短路’,当&&被应用时,若任意一处表达式中出现结果为0,则不再往后运行(我必须全1才为1,这里都有个0了结果肯定是0,我就偷个懒吧==);同理,||在式中做判断时,一旦遇到一处结果为1,便不在往后进行,直接返回结果;
现在是不是发现了这个题的套路了?
i1结果:
在这里插入图片描述
i2结果:
在这里插入图片描述
怎么样,是你期望的结果吗?

8.条件操作符
exp1?exp2:exp3;

我们翻译一下:表达式1成立吗?如果成立,执行表达式2,如果不成立,执行表达式3
是不是想到了if else语句,我们来替换一下:

if(exp1)
{
    exp2;
}
else
{
     exp3;
}
9.逗号表达式
exp1,exp2,exp3...expN;

这个只需记住一点,逗号表达式从左向右依次执行,整个表达式的结果是最后一个表达式的结果;

10.整形提升

什么是整形提升?

当表达式中任何长度小于int长度的整形(char,unsigned char,short)类型值,都必须先转化为int型或unsigned int类型,才能够被CPU运算;这一过程相对于我们常用的强制类型转换,是隐式类型转换,是在运行时默认进行的,但掌握这一过程对我们规避运算错误,和认识计算机工作方式很有帮助.

整形提升是按照变量的符号位来进行提升的,当数据类型为无符号时,则用零来补全;

char a= -1;
//a变量里真正储存的数据(补码):11111111;//第一位是符号位
//在表达式里按照符号位进行提升为int型:
11111111 11111111 11111111 11111111
char b= 1;
//真正存储数据:00000001;
//进行整形提升后:
00000000 00000000 00000000 00000001

这里来应用一下:
求输出结果:

int main()
{
    char a = -20;
    unsigned int b = 10;
    printf("%u",a+b);
    return 0;
}

是-10吗?
我们来使用整形提升的思路分析一下:
当计算a+b时首先要对a进行整形提升:

a 的原码:10010100
a 的反码:11101011
a 的补码:11101100//好,这里我们边找到了a在内存里真正存储的值;
对a进行整形提升:11111111 11111111 11111111 11101100
而b在内存里的是:00000000 00000000 00000000 00001010
这时cup的整形运算器(ALU)才会将这两个数相加
得到:11111111 11111111 11111111 11110110
因为输出的是无符号整型,最高位是数据位,所以结果应该是2^32-1-9 = 4294967286;

我们来看一下运算结果:
在这里插入图片描述
所以,掌握了整形提升,在遇到这种情况时就会有迹可循。

C的操作符还有很多妙用和功能,水平有限就先写到这里,如果你有更多相关的知识,欢迎在博客下方评论哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值