C语言之路第十一天:操作符详解

一,算术操作符:

+ - * / %(加减乘除):

/中如果除数与被除数都是整数形式,得到的是商,有余数;如果至少有一个是小数则所得的结果是小数形式。

%(取模,即取余数)这个操作符两边必须是整数,不能是浮点数。

二,移位操作符

右移操作符(>>);

        1算术右移:右边超出部分舍去,左边补 原符号位

        2逻辑右移:右边超出部分舍去,左边补0

 整数的二进制表示有:原码,补码,反码,在内存中以补码的形式存储

对于正整数来说,原码,反码。补码都是相同的,

对于负数(以-1为例)

原码:10000000000000000000000000000001

反码:1111111111111111111111111111111111110(符号位不变,其他位按位取反)

补码:1111111111111111111111111111111111111(反码+1)

 对于-1,右移,无论右移多少位,左边都一直补1,其补码不变,原码也不变,因此-1的算术右移总是-1

左移操作符(<<):

左边超出部分丢弃,右边补零

注意:对于位移操作符,移动的位数不要是负数,这是一个未定义行为,位移操作符只能作用于整数。

三,位操作符(二进制位):只能作用于整数

按位与(&):对应位都为1,才为真(1),否之为假(0)

按位或(|):对应位至少有一个为1,就为真(1),全为0才为假(0)

按位异或(^):对应位相同为假(0),对应位相异,为真(1)

注意计算机中都是拿补码进行运算的,因此负数需要先计算出补码再进行,与,或,异或

 下面看几个例子:

1,不用中间变量交换a 和 b的值

 2,求一个数存储在内存中二进制中1的个数

 四,赋值操作符(=)

变量初始化:数据类型 变量名= 值

赋值:变量名=值(已经有值,改变值叫赋值)

常见的赋值符号:

 例如:

 

五,单目操作符(只有一个操作数)

 !a:将a的真假性变换,假变真,真变假

&:&a取出a的地址,一般与指针配合使用

 sizeof :用来求大小的,单位是字节

 数组去掉数组名,得到的就是数组类型,方括号里面的数字,影响数组的大小

 注意这个代码:注意s的类型是short短整形,s=a+5之后,s依然是短整形,多余部分将被截断,因此第一个打印结果是2个字节,而在sizeof内的计算并不是真正的计算,不会改变变量的大小,因此,s的值依然是0。

看一个有关sizeof的题:

 这里很容易直到(1)(3)打印的值分别为:40,10,但是(2)(4)呢,这里不要忘记,当把数组传给函数时候,传的是首元素的地址,也就是说是一个指针变量,在32位机上是4个字节大小,在64位机上是8个字节大小。

~:按位取反(按二进制位)

 故~0为-1;

一个应用场景(指定位改变二进制数)

 ++与--:前置是先++或--再使用,后置是先使用再++或--

六,关系操作符

 七,逻辑操作符

逻辑与(&&):两边都为真,得到的才是真

逻辑或(||):至少有一边为真结果就为真

注意:逻辑与和逻辑或注意的这个数的本身

           按位与和按位或主义的是俩数的二进制对应位

逻辑与(&&)如果左边的结果已经是假,那么 不管右边什么就不会再计算了。如:

 这个程序输出为1 2 3 4

原因:a++是先使用a的值,则&&左边是假,后面的 ++b和d++都不会再计算

只有a++,故1,2,3,4

如果将a=0改为a=1,那么都将会计算,执行的结果是2 3 3 5

逻辑或(||)如果左边是真,不管右边是啥都不会再计算

 这个结果是:2 3 3 4,原因是a=1,||左边已经是真,则||右边的不管是啥都不会运算

综上:对于逻辑与:如果左边是假,右边将不会再计算,直接返回假

           对于逻辑或:如果左边是真,右边也不会再计算,直接返回真

八,条件表达式

exp1?exp2:exp3

解释:如果表达式1为真,就执行表达式2,并且表达式2的结果是整个表达式的结果,如果表达式1为假,就执行表达式3,并且表达式3的结果就是整个表达式的结果。

例如:

 

 需要注意的是,写条件表达式不要写的过于复杂,不利于阅读代码。

九,逗号表达式

有逗号隔开的多个表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果。

a>b不产生执行结果,a=b+10,得到a=12.a不产生执行结果,b=a+1,得到b=13,因此这个c的值是13

 

 这个真正起到作用的是后面d>0的判断,但是在判断之前,前面的表达式还是要计算的

 对于逗号表达式如果不熟悉就不要使用,老老实实的写代码才是硬道理

十,其他操作符

下标引用操作符:[],有两个操作数,分别是数组名,索引数

函数调用操作符:()至少有一个操作数(函数名),传入的参数也是操作数

结构体操作符:.和—>

先创建一个结构体:

 对于结构体的访问:

即:结构体变量名.成员名

或者通过指针变量

结构体指针—>成员名

表达式求值:

表达式求值的顺序一部分是由操作符的优先级和结合性决定的,同时有些表达式的操作数在求值时需要数据类型转换

1,隐式类型转换

C的整型算术运算总是至少以缺整型类型的精度进行的,为了获得这个精度,表达式中的字符和短整形在运算前转化为普通整型,这称为:整型提升

 对于定义一个比整型小的数据,让他等于一个整型,则要按照所定义的数据类型大小进行截断char只保留一个字节,short只保留2个字节,之后在进行整型运算的时候要进行整型提升,有符号的数按照符号位(也就是原最高位)补在左边,无符号的数,直接补0

例如:

 这个程序,c是char类型,本应是一个字节,但是+c做了整型运算,被整型提升为4个字节

 算术转换:如果某个操作符的操作数的类型不同,除非其中一个操作数类型转换为另一操作数类型,才能计算

 

一个操作符如果出现以上两种或两种以上的操作数, 就要进行整型转换,将所占内存小的转换为所占内存大的。

操作符的属性:复杂表达式求值有三个影响:操作符的优先级;操作符的结合性;是否控制求值顺序

 

对于这个求值表达式,有一下可能路径 

,可能的路径:

这就导致可能在不同的编译器出现不同的结果,这种程序是有问题的,自己写的时候要避免

还要这个,c到底是--之前还是之后的值呢,就会有歧义 

 同样,这段程序,下面调用了三次fun,不同顺序会导致fun返回的结果不同,因此是有问题的。

通过以上这几个例子告诉我们,要尽量避免写复杂的表达式求值,可以多创建几个中间变量,一步步来写。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值