前言:
在大家学习语言或者使用语言的过程中,经常会遇到各种各样的操作符计算,由于大家学习时间跨度比较大,或者基础不扎实等问题,经常会将操作符相关问题搞混。在此,特地为解决上述问题,写了一篇博客以期能够帮助大家!
操作符的分类:
- 算术操作符:+、-、*、/、%
- 移位操作符:<< >>
- 位操作符:&、|、^、~
- 赋值操作符:=、+=、-=、*=、/=、%=、<<=、>>=、&=、|=、^=
- 单目操作符:!、++、--、&、*、+、-、sizeof、(类型)
- 关系操作符:>、<、<=、>=、==、!=
- 逻辑操作符:&&、||
- 条件操作符:?:
- 逗号表达式:,
- 下标引用:[ ]
- 函数调用:()
- 结构成员访问:. 、->
1.算术操作符
对于算术操作大家应该比较熟悉,在我们从小到大的学习生活中经常会用到,但是值得注意的是这里面的“/”与“%”操作符的使用,在计算机语言中的使用可能与大家之前接触的不太一样,大家可能经常会搞混淆。在此,特地为大家总结一下,方便大家学习。
1.1 / 用来执行除法
“ / ”的两个操作符都为整数,那么最终计算结果也只会返回整数部分。
举例代码如下:
根据运行结果大家可以看到,尽管a是float(浮点数)类型,但是其运行结果仍然只是保留了整数部分!原因是在C语言中,整除只会最终保留整数部分,舍去小数部分。这里注意小数部分不是四舍五入,而是直接舍弃!
要想实现最终返回值包含浮点数部分,那么“ / ”的两个操作数至少有一个要是浮点型的数字。
举例代码如下:
趁热打铁:
对于这个计算结果,大家可能还心存疑惑,难道结果不应该是2嘛?注意,这边就是用到上面提到的内容,C语言中的整除会舍弃小数,这边 (a / 100)的结果是0,所以最终运行的结果会是0!
1.2 % 用来执行取余(取模)
%在C语言中这个叫取模运算符,其操作数只能是整数,不能用于浮点数。其运算结果返回的是操作数相除的余数。
举例代码如下:
特别声明:对于负数的取模运算,正负决定于第一个操作数的正负。
举例代码如下:
2.移位操作符
<< 左移操作符:
>> 右移操作符:
注意1:移位操作数只能是整数!并且操作符的作用对象是二进制的补码,故在此之前希望大家熟悉在计算机内部的计算法则和原码、反码、补码的相关知识点。这部分内容,我也会在后期专门出一个文章来介绍。
注意2:对于移位操作符,不能移动负数位。这个标准是未定义的。
例如:
2.1左移操作符:
在二进制补码序列中,采取的规则是:左边抛弃,右边补0。
举例代码如下:
基于二进制补码的微观操作如下:
2.2右移操作符:
规则是:右边抛弃,左边用该数的符号位补充。但是要注意区分正数和负数的区别!
正数的二进制补码最左边的为0,负数为1。
3.位操作符
注意:也都是在二进制补码中进行计算。
运算规则:对于两个操作数的补码,进行上下对照,然后按照运算规则得出一个新的序列。
- & :两个有0就是0,全为1才是1;
- | :两个有1就是1,全为0才是0;
- ^ : 两个相同为0,相异为1;
- ~ :是一个单目操作符,将操作数的补码全部取反,即0变成1,1变成0;
举例代码如下:
一道变态面试题:
//变态面试题:实现两个数字交换(在不创建第三个变量的前提下)
int main()
{
int a = 3;
int b = 6;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("%d %d", a, b);
return 0;
}
4.赋值操作符
赋值操作符相对来说比较好理解。但是在这边特别需要关注两个点。
- 区分“ = ”与“ == ”: “ = ”用于赋值,比如在给变量进行初始化时;“ == ”代表的时等于,等价于我们日常生活中两个数字相等。
- 其余的赋值操作符都有相同的运算法则。
举例代码如下:
int main()
{
int a = 10;//这边给a赋值为10
int b = 20;//这里给b赋值为20
int a = b;//这里是将b的值赋值给a
a += b;//等价于:a = a + b;
a <<= b;//等价于:a = a << b;
//剩下的依次类推,有共同的运算法则
return 0;
}
5.单目操作符
“单目”的意思时其操作数只有一个,这边需要特别强调的几个操作符。
- !:表示逻辑非,意思是不是这个数,一般用于条件判断;
- ++、--:这两个操作符要注意放在左边还是右边,如果放在左边,是先对于式子结果进行+1,然后再对于操作数+1;如果是在右边的话,是先对于操作数+1,然后再对于式子结果+1。
- sizeof: 是用来求数组或者类型的长度。
- *:表示解引用操作符,用在指针中,对于明确指针变量p中存放的地址,通过*p,可以找到对应地址所指向的数据或者字符。
举例代码如下:
// !
int main()
{
int flag = 1;
if (!flag)//等价于flag != 1时
{
printf("yes");
}
else
{
printf("no");
}
return 0;
}
// ++ --
int main()
{
int a = 10;
int b = a++;
printf("%d %d", a, b);
//a = 11、b = 10;
//这是在右边进行++的运算结果
}
//sizeof
int main()
{
int arr[10] = { 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
return 0;
}
6.关系操作符
这部分操作符也相对容易理解,主要用于判断操作数之间的关系。
7.逻辑操作符
- && :代表逻辑与
- || :代表逻辑或
二者主要用于if语句中,将两个条件建立联系。
int main()
{
int a = 10;
int b = 20;
if ((a - b) < 0 && a < 20)//当&&两个条件同时成立的时候,打印yes
{
printf("yes");
}
if ((a - b) < 0 || a < 20)//当||两个条件成立一个的时候,打印yes
{
printf("yes");
}
}
8.条件操作符
对于条件操作符,只需要记住如下运算法则:
9.逗号表达式
就是用逗号将表达式分隔。计算方式为从左到右,整个表达式最终结果为最右边表达式的结果。
举例代码如下:
//一般形式:int c = exp1, exp2, ...,expn
int main()
{
int a = 0;
int b = 0;
int c = 0;
int d = (++a, b++, c = a + b);
printf("%d", d);
//d = 2;
return 0;
}
常用做法举例:
可以用来简化条件多个运算表达式。由下列代码可以看出,方案2相对于方案1更为简便。
//方案1
int main()
{
int a = 3;
int b = 5;
int c = 6;
a + b;
a - b;
while(c > 0)
{
a + b;
a - b;
printf("%d", (a + b) + (a - b));
}
return 0;
}
//方案2
int main()
{
int a = 3;
int b = 5;
int c = 6;
while (a + b, a - b, c > 0)
{
printf("%d", (a + b) + (a - b));
}
return 0;
}
10.下标引用 [ ] ,函数调用( )
- [ ]下标引用操作符,主要用在数组中访问数组元素,其本质上也属于一种操作符,其操作数为数组名+访问数组序号。
int main()
{
int arr[10] = { 0 };
int ret = arr[7];
//这里的arr和7为[ ]的操作数
return 0;
}
- ( )函数调用操作符,主要用于函数调用,其操作数至少为一个,就是函数名,也可以由更多操作数,在( )内可以加入更多参数。
void test1()
{
printf("yes");
}
int test2(int a, int b)
{
return a + b;
}
int main()
{
int a = 0;
int b = 0;
test1();//test为()的操作数,且这是操作数为1个
int c = test2(a, b);//这里的操作数为3个,分别是 test2, a, b
printf("%d", c);
return 0;
}
11.结构成员访问:. 、->
这两个操作符主要用在结构体中,来对结构体中的成员变量进行访问。
- 、 :主要用于对结构体成员变量的直接访问。
- -> : 主要用于对结构体成员变量的间接访问(指向结构体的指针变量)。这个设计的内容较为复杂,需要在大家熟练掌握指针和结构体相关知识点时才能更好的学习。在作者后期的博客也会有介绍,欢迎大家查询学习。
struct student {
int x;
int y;
}pa = {1,2};
int main()
{
printf("%d %d", pa.x, pa.y);
//输出结果为 1 2
return 0;
}
以上是操作符的分类及其用法的总结,希望大家能够通过这篇文章更好了解操作符相关知识!同时由于作者知识水平有限,可能会存在更好的表达方法或者存在错误,也欢迎各位老师能够在评论区批评指正!