> 文档中心 > C语言:操作符详解

C语言:操作符详解

目录

算数操作

+(加)

-(减)

*(乘)

/(除)

%(取模)

移位操作符

<<(左移操作符)

>>(右移操作符)

位操作符

&(按位与)

^(按位或)

|(按位异或)

赋值操作符

=

+=

-=

*=

/=

&=

^=

|=

>>=

<<=

逻辑操作符

&&(并且)

||(或者)

条件操作符

exp1 ? exp2 : exp3

逗号操作符

exp1, exp2, exp3, …expN

&(取地址操作符)*(解引用操作符)

操作符一览表


算数操作符

  • +(加)

  • -(减)

  • *(乘)

  • /(除)

  • %(取模)

前四种加减乘除很好理解,举个例子,代码如下:

#includeint main(){int a = 10;int b = 5;int c = a + b;int d = a - b;int e = a * b;int f = a / b;printf("%d %d %d %d \n", c, d, e, f);}

运行结果如下:

第五种%是取模运算符,就是一个数对一个数取余数,举个例子,10%3就是10/3余1,结果就为1,所以10%3=1

//注意:取模(%)运算符只能对整数进行操作,不可以对浮点数或其他数据类型进行操作

举个例子,代码如下:

#includeint main(){int arr[10] = { 1,2,3,4,5,6,7,8,9 ,10 };int i = 0;for (i = 0; i < 10; i++){if (arr[i] % 3 == 0){printf("%d ", arr[i]);}}}

 创建arr数组,遍历数组,arr[i]%3==0即找出arr数组中3的倍数

运行结果如下:


移位操作符

  • <<(左移操作符)

  • >>(右移操作符)

//注意:移位运算符只能对整数进行操作,不可以对浮点数或其他数据类型进行操作

移位操作符移动的是数据的补码,因为在内存中整数是以二进制补码的形式来存储。

对二进制补码不了解的可以看  C语言:数据存储 这一篇博客,链接:

左移:左边丢弃最高位,右边补0

举个例子,代码如下:

#includeint main(){int a = 1;//a的补码 00000000 00000000 00000000 00000001int b = a << 1;//b的补码 00000000 00000000 00000000 00000010printf("%d ", b);}

a的补码左移丢弃左边最高位,右边补0再赋值给b,b是正数,原码反码补码相等,所以b的值应该等于2

运行结果如下:

左移n位相当于对原数据乘2的n次方(不考虑溢出的情况)


右移分为两种情况:逻辑右移 算数右移

        逻辑右移:右边丢弃最低位,左边补0

        算数右移:右边丢弃最低位,左边补符号位

右移操作符具体在使用时是哪一种情况取决于编译器如何处理

举个例子,代码如下:

#includeint main(){int  a = -1;//a的原码 10000000 00000000 0000000000000001//a的反码 11111111 11111111 1111111111111110//a的补码 11111111 11111111 1111111111111111int b = a >> 1;printf("%d ", b);}

这里我们也不知道编译器会如何处理,我们只能根据运算结果逆推出编译器运用的是逻辑右移还是算数右移

运行结果如下:

 假设一下,如果是逻辑右移,左边补0,右边丢弃

那么符号位就是0,也就是说b应该是正数,打印出来应该是正数,但是结果却是负数。说明编译器采用的是算数右移。

//算数右移的逻辑性更强,考虑符号位,而逻辑右移不考虑符号位,直接补0


位操作符

  • &(按位与)

  • ^(按位或)

  • |(按位异或)

//注意:位操作符只能对整数进行操作,不可以对浮点数或其他数据类型进行操作

这三种操作符都是对位进行操作,所以叫做位操作符,这里的位指的是二进制补码位

&(按位与)

有0为0,同1为1

举个例子,代码如下:

#includeint main(){int a = 1;int b = 2;//a的补码 00000000 00000000 00000000 00000001//b的补码 00000000 00000000 00000000 00000010int c = a & b;printf("%d ", c);}

对a和b相同位置的位进行按位与操作,什么意思呢?看图:

 就像红线连起来的两个位一样,对这两个位进行操作,剩下的位也一样,就会得到新的补码

按照运算规则,c的补码应该是00000000 00000000 00000000 00000000

c的结果应该是0,那么是不是0呢?运行结果如下:


|(按位或)

有1为1,同0为0

举个例子,代码如下:

#includeint main(){int a = 1;int b = 2;//a的补码 00000000 00000000 00000000 00000001//b的补码 00000000 00000000 00000000 00000010int c = a | b;printf("%d ", c);}

按照运算规则,c的补码应该是:00000000 00000000 00000000 00000011

结果应该是3,那么是不是3呢?

运行结果如下:


^(按位异或)

相同为0,相异为1

举个例子,代码如下:

#includeint main(){int a = 1;int b = 2;//a的补码 00000000 00000000 00000000 00000001//b的补码 00000000 00000000 00000000 00000010int c = a ^ b;printf("%d ", c);}

按照运算规则,c的补码应该是:00000000 00000000 00000000 00000011

结果应该是3,那么是不是3呢?

运行结果如下:


赋值操作符

  • =

  • +=

  • -=

  • *=

  • /=

  • &=

  • ^=

  • |=

  • >>=

  • <<=

这一类运算符就是属于简化代码的操作符

举个例子,代码如下:

#includeint main(){int a = 1;int b = 2;b += a;printf("%d ", b);}

b += a  和  b = b+a  的效果是一样的,只不过简化了一下代码,剩下的操作符也是类似的


逻辑操作符

  • &&(并且)

  • ||(或者)

&&(并且)

只有前后两个表达式都成立,才为真,否则为假

举个例子,代码入下:

#includeint main(){int a = 1;int b = 2;if (a > 0 && b > 0){printf("%d 和 %d 都是正数\n", a, b);}else{printf("%d 和 %d 中有不是正数的\n", a, b);}}

if语句里面要求a和b都要>0,这时才为真,可以进入if语句

运行结果如下:

&&操作符使用时,只要有一个为假,后面的表达式就不再运行,因为这时结果已经为假了,再运行也是浪费时间

举个例子,代码如下:

#includeint main(){int a = 1;int b = -2;int c = 0;if (b > 0 && (c = a) > 0){printf("hehe\n");}printf("%d ", c);}

if语句中要求b>0并且把a的值赋给c ,要求c>0,然而,b>0就已经为假,后面的表达式就不会执行,也就是说,a赋值给c的表达式不会执行,如果执行的话,那么c的值就为1,结果到底是怎样的呢?我们一起来看

运行结果如下:

 结果如我们所料,b>0表达式为假了,后面的c=a根本就没有执行,c还是为0


||(或者) 

前后两个表达式有一个成立就为真

举个例子,代码如下:

#includeint main(){int a = 1;int b = -2;if (a > 0 || b > 0){printf("%d 和 %d 中有正数\n", a, b);}else{printf("%d 和 %d 都是负数\n", a, b);}}

if语句要求只要a和b中有一个>0就为真,可以进入if语句

运行结果入下:

 ||操作符使用时,只要有一个为真,后面的表达式就不再执行,因为这时结果已经为真了,再运行也是浪费时间

举个例子,代码入下:

#includeint main(){int a = 1;int b = -2;int c = 0;if (a > 0 || (c = a) > 0){printf("hehe\n");}printf("%d ", c);}

if语句中要求a>0或者a赋值给c后c>0即可进入if语句,然而,a>0已经为真,后面的表达式就不再执行,也就是说,c=a不会执行,那么运行出来的结果是怎样的呢?我们一起来看

运行结果如下:

  结果如我们所料,a>0表达式为真,后面的c=a根本就没有执行,c还是为0


条件操作符

exp1 ? exp2 : exp3

这是c语言唯一一个三目操作符,就是需要三个操作数的操作符

个人感觉这就是if-else 语句的化简版

如果exp1成立就会返回exp2,否则返回exp3

举个例子,代码如下:

#includeint main(){int a = 3;int b = 5;int c = a > b ? a : b;printf("%d ", c);}

a>b为假,那就应该返回b,答案是不是5呢?

运行结果如下:


逗号操作符

exp1, exp2, exp3, …expN

从表达式1开始运行一直运行到最后一个表达式,最后返回最后一个表达式的结果

举个例子,代码如下:

#includeint main(){int a = 3;int b = 5;int c = (b += a, a += b, a + b);printf("%d ", c);}

 先运行b+=a,那么b=8,再运行a+=b,那么b=11,再运行a+b,最终返回a+b就是11,那么结果是不是19呢?

运行结果如下:


&(取地址操作符)*(解引用操作符)

这两个操作符互为逆运算

&作用是取出地址,*作用是通过指针找到指针指向的内容

举个例子,代码如下:

#includeint main(){int a = 3;int* p = &a;*p = 5;printf("%d ", a);}

取出a的地址放到指针p里面,再对p解引用相当于找到了a,对*p赋值为5,就相当于对a赋值,那么a应该等于5,那么是不是5呢?

运行结果如下:


操作符一览表

  • 优先级

运算符

名称或含义

使用形式

结合方向

说明

1

[]

数组下标

数组名[常量表达式]

左到右

--

()

圆括号

(表达式)/函数名(形参表)

--

.

成员选择(对象)

对象.成员名

--

->

成员选择(指针)

对象指针->成员名

--

2

-

负号运算符

-表达式

右到左

单目运算符

~

按位取反运算符

~表达式

++

自增运算符

++变量名/变量名++

--

自减运算符

--变量名/变量名--

*

取值运算符

*指针变量

&

取地址运算符

&变量名

!

逻辑非运算符

!表达式

(类型)

强制类型转换

(数据类型)表达式

--

sizeof

长度运算符

sizeof(表达式)

--

3

/

表达式/表达式

左到右

双目运算符

*

表达式*表达式

%

余数(取模)

整型表达式%整型表达式

4

+

表达式+表达式

左到右

双目运算符

-

表达式-表达式

5

<< 

左移

变量<<表达式

左到右

双目运算符

>> 

右移

变量>>表达式

6

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

小于

表达式<表达式

<=

小于等于

表达式<=表达式

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

8

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

表达式1?

表达式2: 表达式3

右到左

三目运算符

14

=

赋值运算符

变量=表达式

右到左

--

/=

除后赋值

变量/=表达式

--

*=

乘后赋值

变量*=表达式

--

%=

取模后赋值

变量%=表达式

--

+=

加后赋值

变量+=表达式

--

-=

减后赋值

变量-=表达式

--

<<=

左移后赋值

变量<<=表达式

--

>>=

右移后赋值

变量>>=表达式

--

&=

按位与后赋值

变量&=表达式

--

^=

按位异或后赋值

变量^=表达式

--

|=

按位或后赋值

变量|=表达式

--

15

逗号运算符

表达式,表达式,…

左到右

--

 多个运算符时,优先级高的先运算