操作符的分类:算数操作符、移位操作符、位操作符、赋值操作符、单目操作符、关系操作符、逻辑操作符、条件操作符、逗号表达式、(下标引用、函数调用和结构成员)。
一、算数操作符(+、-、*、/、%)
其中加减乘除的操作符我们都很熟悉了,但是进行除法运算的时候还是要注意以下内容:
对于除号(/)来说,如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
对于取模操作符(%)操作符来说,它的两个操作数必须为整数,返回的是整除之后的余数
二、移位操作符(<<、>>)
左移操作符(<<):左边丢弃,右边补零
右移操作符(>>):1.算术右移:右边丢弃,左边补原符号位
2.逻辑右移:右移丢弃,左边补零
对于C语言中算数右移和逻辑右移由什么决定这个问题,博主查阅了相关的资料,大家可以参考:
C语言右移操作符的算数右移和逻辑右移是由编译器决定的。对于有符号类型的数据,编译器可以选择采用逻辑移位还是算术移位。在算术移位中,右移时会在高位补符号位,即如果原数为正数,则在高位补0,如果原数为负数,则在高位补1。而在逻辑移位中,不考虑符号位,移位的结果只是数据所有的位数进行移位。因此,对于有符号数而言,逻辑位移没有太大意义,如果一个负数,逻辑右移,结果就会变成正数。如果想达到逻辑右移的效果,可以使用强制类型转换将有符号数转换为无符号数,然后进行逻辑右移操作。
注意:对于移位运算符,不要移动负数位,这是个是标准未定义的。
整数的二进制表示形式有三种:
原码:直接根据数值写出的二进制序列就是原码
反码:原码的符号位不变,其他位按位取反就是反码
补码:反码+1,就是补码
三、位操作符(&【按位与】、|【按位或】、^【按位异或】)
三者的操作数必须是整数
&【按位与】:同真则真,一假则假
|【按位或】:一真则真,全假则假
^【按位异或】:相同为假,相异为真(相同为零,相异为一)
&的应用
int main()
{
int a = 3;
int b = 5;
int c = a & b;
//a:00000000000000000000000000000011
//b:00000000000000000000000000000101
//c:00000000000000000000000000000001
printf("%d\n", c);//因此最终输出结果为1
return 0;
}
|的应用
int main()
{
int a = 3;
int b = 5;
int c = a | b;
//a:00000000000000000000000000000011
//b:00000000000000000000000000000101
//c:00000000000000000000000000000111
printf("%d\n", c);//因此最终输出结果为7
return 0;
}
^的应用
int main()
{
int a = 3;
int b = 5;
int c = a & b;
//a:00000000000000000000000000000011
//b:00000000000000000000000000000101
//c:00000000000000000000000000000110
printf("%d\n", c);//因此最终输出结果为6
return 0;
}
利用这个知识点,可以做出下面的试题,在此附上链接:不创建临时变量,实现两个数字的交换【C语言实现】(多种方法由浅入深)(不看后悔系列)-CSDN博客
请利用以上知识点 求一个整数存储在内存中二进制位1的个数
int main()
{
printf("请输入数字:");
int num = 0;
scanf("%d", &num);
int count = 0;
int i = 0;
//00000000000000000000000000001110
for (i = 0; i < 32; i++)
{
if (((num >> i) & 1) == 1)
{
count++;
}
}
printf("该数字二进制位中1的数量为:%d\n", count);
return 0;
}
四、赋值操作符(=、+=、*=、/=、<<=、>>=、%=)
赋值操作符可以连续使用,例如
int a = 10;
int x = 0 ;
int y = 20 ;
a = x = y+1 ;//连续赋值
//语意相同,下面的写法更加清晰而且易于调试和理解
x = y+1 ;
a = x ;
+=、-=等复合赋值符,都是进行运算后把运算的结果返回左边变量的。
五、单目操作符(!、-、+、sizeof、~、++、--、(类型))
!可以把真的值变为假,把假的值变为真
-、+在这里代表的是正负号
sizeof是一个操作符,不是函数
int arr[10]={ 0 };
printf("%d\n",sizeof(arr)) ;//单位是字节
//sizeof还有下面的用法
printf("%d\n",sizeof(int [10])) ;//int [10]是arr数组的类型
下面给大家带来一道习题:
在这个题目中,sizeof计算的是s所占空间的大小,而s的空间是提前开辟好的2个字节,不会因为加上了一个整形就变大空间,这里会发生从int到short的截断 ;而下面打印结果为5的原因是sizeof括号中放的表达式是不参与运算的。
~:对一个数的二进制位按位取反
++、--分为两种情况:前置++、-- ——先使用,再计算
后置++、-- ——先计算,再使用
在本例中我们发现,a++操作在打印时先把原本a的值赋给了b,该运算完成后进行了++操作而后赋给了a,由此可以证明前面论述正确。
六、关系操作符(>、>=、<、<=、!=、==)
这些关系操作运算符比较简单,但是我们应该注意一些陷阱
=是赋值,==是判断相等
在比较两个字符串是否相等时,不能使用==,应该使用strcmp,并且注意头文件的引用
七、逻辑操作符(&&)(||)
&&:逻辑与——两边同时为真才为真
||:逻辑或——两边有一个为真则为真
这道题的输出结果为a=1,b=2,c=3,d=4 .这和我们的预期结果可能不同,出现这种问题的原因是:
在进行a&&b运算时,由于&&操作符只有当两边同时为真时才为真,因此当a为假的时候后边的计算不论是什么都不重要了,因为结果必然是假,所以&&操作符后边的不再进行运算。
下面我们再来道题巩固一下:
这道题跟前面的其实差不多,在进行完第一轮操作符||的运算后,后面的运算实际上是没有必要的,所以d++这一步程序实际上没有被执行,所以得到了这个结果。
八、条件操作符(三目操作符 exp1?exp2:exp3)
该操作符的含义其实比较简单:exp1为判断,当判断结果为真的时候就返回exp2,为假的时候就返回exp3.下面是应用实例:
九、逗号表达式
exp1,exp2,exp3,...expN
逗号表达式,就是用逗号隔开的多个表达式。逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
例如,在本题中d的值就为最后一个表达式的值10.
十、下标引用、函数调用和结构成员
其中下标引用和函数调用我们都已经非常熟悉了,但还是要注意以下两点:
数组中元素的下标是从零开始的 ;函数调用时后面的()不论是传参还是不传参都要带上,例如Add().
实际上结构体的调用还有其他的方式:结构体指针->成员名,应用如下,可以发现依然可以打印。