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