C语言 操作符

本文详细介绍了C语言中的各类操作符,包括算术、移位、位、赋值、单目、关系、逻辑、条件、逗号表达式以及数组引用、函数调用和结构体操作。重点讲解了整型提升和隐式类型转换的概念,以及表达式求值的影响因素。
摘要由CSDN通过智能技术生成

操作符分类

算术操作符

移位操作符

位操作符

赋值操作符

单目操作符

关系操作符

逻辑操作符

条件操作符

逗号表达式

数组引用、函数调用、结构体成员访问操作符

操作符详解

算术操作符

+   -   *   /   %

算术操作符中要注意的就是除号和取模。除号有整数的除法和小数除法,只有当除数或被除数至少有一个浮点数才会执行浮点数除法。

取模%计算的是整除之后的余数,两个操作数都必须是整数。

移位操作符

左移操作符和右移操作符:  <<  、 >>

这两个移位操作符的操作数只能是整数(无符号数当作正整数处理)

注意移位操作符是对操作数的二进制位进行移位。在了解移位操作符的作用之前,我们首先要了解一下整数的二进制的三种表示:原码、补码和反码。规定:正整数的原码、反码和补码相同。负整数的反码和补码是需要计算的。0也是可以当成正数,原码反码补码都是00000000 00000000 00000000 00000000.整数在内存中都是以补码的形式存储的,位操作符操作的就是整数的补码。

整数的原码:整数四个字节,也就是三十二个比特位,最高位为符号位,正整数的符号位为0,负整数的符号位为1。

负数反码:原码的符号位不变,其他位按位取反(原来是1的变成0,原来是0的变成1)

负数补码:反码+1

例如-7,-7的原码是 10000000 00000000 00000000 00000111

              -7的反码是  11111111  11111111   11111111   11111000

              -7的补码是  11111111   11111111  11111111   11111001 

对于左移操作符(<<):最左边一位丢弃,右边补0

7的补码: 00000000 00000000 00000000 00000111

int a=7<<1  :     00000000 00000000 00000000 00001110  

此时a的符号位为0,整数的原码反码补码相同,所以a的原码就是他的补码,所以a的值为14

-7的补码  :11111111 11111111 11111111 11111001

int a=-7<<1 :11111111 11111111 11111111 11110010

此时a的符号位为1,我们要根据他的补码来计算原码才能知道a的值

a的反码:11111111 11111111 11111111 11110001

a的原码:10000000 00000000 00000000 00001110

所以a的值是-14

从这里我们可以知道,左移有乘二的效果。

右移操作符:

右移操作其实分为两种,一种是逻辑右移,一种是算术右移

逻辑右移:右边舍弃,左边补0;

算术右移:右边舍弃,左边补原来的符号位

这两者的区别就是左边补的是0还是原来的符号位,对与逻辑右移,简单粗暴,直接补0.而算术右移则是补原符号位。这样看来是算术右移更加合理,而事实也是现在绝大部分编译器采用的都是算术右移,对于逻辑右移,我们做了解就好。

例如

int a=7>>1;   7的补码:00000000 00000000 00000000 00000111

                     a的补码:00000000 00000000 00000000 00000011

所以a的值为3

int a=-7>>1:  -7的补码:11111111 11111111 11111111 11111001

                      a的补码:11111111 11111111 11111111 11111100

                      a的反码:11111111 11111111 11111111 11111011

                      a的原码:10000000 00000000 00000000 00000100

所以a的值为-4

注意:移位操作符只能移动正数个位,不能移动负数位,这是标准未定义的。如7>>-1

位操作符

(按位与)&     (按位或) |     (按位异或 )^

这里的位也都是指的二进制位,他们的操作数也只能是整数,操作的对象也是整数的补码。

计算方式

按位与&:对应的二进制位两个同时为1才为1,有0则为0

按位或 | :对应的二进制位两个同时为0才为0,有1则为1

按位异或 ^ :对应的二进制位相同则为0,不同则为1

位操作符和移位操作符结合在一起是能够实现很多有趣的功能的,比如将数据的特定的一个二进制位改为0或1,我们可以很轻松的使用这是操作符来达到。

对于按位异或操作符还有下面这种做法

不创建临时变量,交换两个变量的值

int a=10;

int b=10;

我们可以这样做:

a=a^b;

b=a^b;

a=a^b;

通过这个案例我们可以发现,异或两次相同的数就等于原来的数,因为两个相同的数异或为0,而任何数与0异或都是原来的数,同时我们也可以得知异或是满足交换律的。当然,上面那个案例我们也可以用加法来解决,都是用加法就要考虑两个数的和是否会栈溢出的情况了。

赋值操作符  

  =      赋值也可以连续赋值,但是不适合调试,可读性也不好,不建议连续赋值。如a=b+2=c+5;

  复合赋值:+=  -=  *=  /=  <<=  >>=  &=  |=  ^= 

单目操作符

单目操作符就是只有一个操作数的操作符。

!(逻辑反操作) 将真的变成假的,假的变成真的  如 ! 1的结果就是0

+(正值)  -(负值)

&(取地址) 取出变量的地址

sizeof(求操作数的类型长度) sizeof是操作符而不是函数,当sizeof的操作数是变量的时候,括                                                       号可以省略,当时类型名的时候,括号不能省略

~  (对一个数的二进制位按位取反,操作的也是补码)

  - -(前置、后置--)  ++(前置、后置++) 看是要先使用还是要先自加自减

*(解引用操作符)对指针进行操作访问指针所指向的对象

(类型) 强制类型转换

关系操作符

>  >=  <  <=  !=  ==

这里要注意的就是判断相等要用 = = ,不用写成一个等号。浮点数的比较和字符串的比较不能用==,浮点数因为在内存中存储的方式本来就存在误差,而字符串判断相等要用strcmp函数

逻辑操作符

逻辑与&&     逻辑或 | | 

要与按位与和按位或区分,逻辑与和逻辑或只关注真假

要注意的是,这两个操作符如果前面的表达式已经能够确定结果了,就不会去判断后面的表达式,后面的表达式中如果有计算也不会执行

条件操作符

也叫三目操作符,表现形式为

表达式1?表达式2:表达式3

表达式1为真,执行表达式2,不执行表达式3

表达式1为真,执行表达式3,不执行表达式2

逗号表达式

用逗号隔开的n个表达式

表达式1,表达式2……表达式n

逗号表达式会从左至右依次计算,最终结果是最后一个表达式的结果

下标引用,函数调用,结构体成员访问操作符

下标引用 : [ ]  [ ]就是下标引用操作符,两个操作数就是数组名和下标。两个操作数也可以换位置,效果是一样的,如arr[i]也可以写成 i [arr]。因为 arr[ i ] 与*(arr+i)是等价的 ,加法交换律 *(arr+i) 与 *(i+arr)也是等价的,于是就可以写成 i[arr]。

函数调用 ( )  函数调用的时候函数名后面的小括号就是函数调用操作符,是不能省略的。

结构体成员访问操作符

.    用于结构体对象

-> 用于结构体指针,等价于*(ps).

表达式求值

表达式求值的顺序一部分是由操作符的优先级和结合性决定,同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型

隐式类型转换

C语言的整型算术运算总是至少以缺省(缺省的意思就是默认)整型类型的精度来进行的。为了获得这个精度,表达式中的字符或短整型操作数在使用之前被转换为普通整形,这种转换称。为整型提升。

为什么要进行整形提升?

因为表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节大小一般就是int的字节长度,同时也是通用寄存器的长度。

如何进行整形提升?

整型提升是按照变量的数据类型的符号位来提升的。

比如char ch=-1.-1的补码是32位1,当时char类型的存储空间只有八个比特位,于是就进行截断,将前面的比特位截断丢弃,后八个比特位存在ch中。当ch要进行整形提升时,把他的最高位看成符号位,高位补符号位1来进行整型提升,于是ch整型提升后位三十二位1。如果存的是1,则截断后的最高位为0,整型提升时高位补0.如果是无符号数,整型提升时直接在高位补0.

举例

char a=5;

char b=126;

char c=a+b;

printf("%d\n",c);

5的二进制补码:00000000 00000000 00000000 00000101

截断后a中存储的二进制序列: 00000101

a整型提升后的二进制序列: 00000000 00000000 00000000 00000101

126的二进制补码:00000000 00000000 00000000 01111110

截断后b存储的二进制序列: 01111110

b整型提升之后的二进制序列:00000000 00000000 00000000 01111110

整型之后相加的结果:00000000 00000000 00000000 10000011

截断后存储到c的二进制序列:10000011

当我们要将c以%d的形式打印时,首先要整型提升,此时c的最高位时1,所以整型提升时高位补1

得到

补码:11111111 11111111 11111111 10000011

反码:11111111 11111111 11111111 10000010

原码:10000000 00000000 00000000 01111101

将原码转换成十进制打印出来就是  -125

整型提升是用于大小小于整型的类型进行整数运算。

算术转换

如果某个操作符的各个操作符属于不同的类型,那么除非其中一个操作数转换为类一个操作数的类型,否则操作无法运行。运算时将内存小的转换成内存大的、

影响表达式求值的因素

操作符的优先级

操作符的结合性

是否控制求值顺序

当我们要写一个很长的表达式时最好分开写,不要写成一行,或者用括号来规定计算顺序。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值