目录
操作符
C语言的操作符的种类很多,作用也是多种多样,那么今天,由小春宝来给大家详细介绍一下各类的操作符。
算术操作符
算术操作符一共有五个分别是:+ - * / %
相信大家对前三个都十分了解,分别就是实际意义上的加,减和乘,那么重点讲解一下剩下两个算术操作符
/运算符的两种性质
1.两个操作数都是整型
这个时候的/运算符的作用是求商,就是只求可以整除的部分的商
2. 其中一个操作数是浮点数
这个时候的/运算符和数学上的除法是没有区别的,所以需要算1/n这类数的时候,正确的写法是以下两种
i=1.0/8;
i=(float)1/8;
当然,这里推荐使用第二种,因为在实际的编写程序的过程中,除数并不一定是一个常量
特殊的%运算符
%运算符有这一个非常特殊的性质:操作数必须是整形
/运算符和%运算符在操作数都是整数的情况下是一种互补的关系,/求商,%求膜(余数)
举个小学数学的例子
5÷2=2。。。1
7÷5=1。。。2
然后我们再看这样一个程序的结果
这样相信大家应该不难理解/和%了吧
位操作符
首先,现在这里统一一下,本篇博客的位指的都是二进制位
移位操作符
1.左移操作符<<
左移操作符的作用是把一个数按照二进制序列进行移位,然后在末端补零
也可以理解为高位舍弃,低位补零,就是前n位舍去,后n位补零
这里教大家一个算左移的小技巧,当进行左移操作时,当一个数前n位都是0的时候,移位之后这个数相当于在原有的基础上乘以一个2^n,当然在进行移位的时候严谨一点还是需要画出二进制序列
2.右移操作符>>
右移和左移是相对的,但是右移有两种形式
1.算术右移(现在的编译器几乎都是这种形式)
低位舍去,高位补符号位,当符号位为1时我们需要多加小心
2.逻辑右移
右边舍去,左边补0
对于无符号的数或者符号数为0,或者进行了逻辑右移,我们都可以简略的认为,移k位为代表处以2^k
逻辑位操作符
1.按位与&
将两个操作数的按照对应的位进行逻辑与,按位与有一个规则就是只有操作数的位都是1的时候按位与结果才为1,其他均为0
2.按位或|
将两个操作数按照对应的位进行逻辑或,只有两个操作数的位都是0,结果才为0,其余都为1
3.按位异或^
看到这个符号^,小伙伴们千万不要认错了,这不是数学中的次方,而是C语言中的按位异或
按位异或的性质是两个操作数的位相同为0,不相同结果为1
但这并不是按位异或的最好用的性质,按位异或具有三个性质:自反性,可交换性,和结合性,
后两个性质相信大家都或多或少可以理解,而第一个自反性的性质就比较好用且重要了
自反性:a^b^b=a;
在以下两个场景可以使用
不定义变量实现两个变量值的交换
#include<stdio.h>
int main() {
int a = 2, b = 5;
printf("a=%d\tb=%d\n", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a=%d\tb=%d\n", a, b);
return 0;
}
这个程序已经实现了两个变量的交换,我们还可以进行简化
a^=b^=a^=b;
接下来我们来证明一下自反性,首先a^b^b 根据结合性,我们可以先算b^b,b和b的位都是一样的,所以结果为0,接下来就是证明自反性的一个关键,任何一个数按照二进制位和0异或都是其本身
我们一个一个位证明即可,如果这个位是0,和0相同,根据异或性质得0,如果是1,和0相异,根据性质得1,所以异或0等于本身,接下来就按照实例来证明
接下来给大家介绍^的另一个好的使用场景
给定一个数组,有一个元素只有一个,其他元素都有两个,找出那个元素
#include<stdio.h>
int main() {
int arr[] = { 1,2,5,6,8,7,7,2,1,8,6 };
int size = sizeof(arr) / sizeof(arr[0]);
int val = 0;
for (int i = 0; i < size; i++) {
val ^= arr[i];
}
printf("%d\n", val);
return 0;
}
利用^的性质便可轻易完成这类题目
赋值操作符
此类操作符比较简单,只需遇上了能够认出就问题不大
= -= += *= /= &= ^= |= >>= <<=
简要介绍一下这些赋值操作符的性质,把等号右边的值赋值给左边
像这些有两个符号的操作符都是 a#=b等价于a=a#b,这里的#是用来表示等号前的这些符号的,没有实际意义
单目操作符
单目操作符的定义就是只有一个操作数
!逻辑反操作符 | C语言标准中,非0为真,0为假,!可以颠倒真假 !(非0的数)=0 !0=1 |
|
-负值 | 与数学中的负号一致,改变数的正负性 | |
+正值 | 与正号一样,整数前的正号可以改变 | |
&取地址操作符 | 取出变量的地址 | |
sizeof | 计算操作数的长度(以字节为单位) | |
~ | 对一个数的二进制位进行按位取反 | |
--自减运算符 | a--;等价于a=a-1; | |
++自增运算符 | a++;等价于a=a+1; | |
*间接访问操作符 | 解引用操作符,根据地址找到元素 | |
()强制类型转换 | int a=(int)3.5;将3.5强制类型转化成int型 |
这里面有两个经常挖坑的运算符++和--,前置和后置的性质不用
前置是先改变后使用,后置是先使用后改变
在讨论前置和后置的区别的时候,往往都不止一个操作符,当++或--优先级更高时,
我们需要考虑前置和后置的区别
用下面这个简单的程序举例
#include<stdio.h>
int main() {
int a = 0,b=9;
a = b++;
printf("a=%d\tb=%d\n", a, b);
a = ++b;
printf("a=%d\tb=%d\n", a, b);
return 0;
}
小伙伴们可以先思考一下这个程序的结果,思考完之后按照答案再思考就能明白什么是先使用后该改变了
关系操作符
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
逻辑操作符
&& | 逻辑与 |
|| | 逻辑或 |
这两个操作符还有一种非常特殊的性质,独断性,当&&前面为假时,表达式为假&&后的不会运算
当||前面为真时也是同样
对于&&和||操作符,都是双目操作符,当有多个逻辑操作符时,
我们需要对将两个操作数和一个逻辑操作符看做一个整体
#include<stdio.h>
int main() {
int a = 0, b = 5, c = 0;
(a++) && (b--) || (++c);
printf("%d %d %d", a, b, c);
}
这个程序的结果是1 5 1,首先a++,a先使用为0,为假,所以b--不操作,然后把a++&&b--看做一个整体,这个整体为假,然后再判定++c
条件操作符
条件操作符,也被称为问号表达式
表达式1?表达式2:表达式3;
表达式1为真执行表达式2,为假执行表达式3
c=a>b?a:b;
等价于
if(a>b)
c=a;
else
c=b;
在求最大或最小值时就可以用问号表达式来简化代码
逗号表达式
表达式1,表达式2,表达式3,……表达式N;
从左到右依次执行,表达式N的值即为表达式的值
四个特殊的操作符
()函数调用操作符 | 函数调用时使用 |
[]下标访问操作符 | p[h]=*(p+h) |
.结构体成员访问操作符 | b.name即找到结构体b中的成员name |
->寻找结构体成员操作符 | *p=&b,p->name等价于b.name |
好了,今天的操作符分享就到这了,下一期分享操作符的其他性质