C语言 操作符详解

一.二进制和进制转换

(一)进制的说明

2进制,8进制,10进制,16进制只是数值的不同表示形式而已。

比如:数值15的各种进制表示形式

2进制:  1111

8进制:  17

10进制:15

16进制:F

他们表示满几进1,比如8进制中表示满8进1,8进制中的每一位数字都由0~7构成。

16进制中的每一位数字都由0~15构成,但为了不被误会,所以将10~15的数字在16进制中分别表示成a b c d e f,即:

0   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15

0   1   2   3   4   5   6   7   8   9    a     b     c      d     e     f

(二)进制之间的相互转换

1.将各种进制转换为十进制:求权重

进制中的每一位数字都有各自对应的权重

比如:10进制中的123:

              百位                          十位                          个位

权重     10^2                           10^1                          10^0

求值      1*100          +             2*10           +             3*1       =         123

2进制也是如此,比如1101

                      1                       1                          0                              1

权重            2^3                    2^2                        2^1                         2^0

求值           1*8           +        1*4           +           0*2             +           1*1   =         13

2.将十进制转换各种进制:算除法,求余数  (要算成几进制,就除以几)

运用除法求余数的方法,比如:将十进制转换为二进制:

因此,要背会二进制的权重,这样能更快的转换为与二进制相关的

                                    1             1            1            1            1           1           1     

二进制中的权重          64          32          16          8            4            2            1

比如:求15(十进制)的二进制,所以即为   1   1   1   1

          求14的(十进制)二进制,所以即为   1   1   1   0

         求30的(十进制)二进制,所以即为   1   1   1   1   0

3.各种进制转换各种进制(实质上还是2进制与10进制之间的转换)

(1)2进制转换为8进制

将二进制的数字从右往左以三个为一组来取,每三个求一个十进制的数字,不够三个的就按那几个求就行,最后算出的数字组合起来就是八进制。

例如:将二进制的01101011转化为八进制

注意:0开头的数字,会被当做八进制,因此,这个八进制为0153.

(2)8进制转换为2进制

同理,若将8进制转换为2进制,就需要将八进制的每一位数字先看成十进制,将他们依次转换为三个二进制数字。

需注意:转换后的二进制数字最前面的0要去掉

(3)2进制转换为16进制

将二进制的数字从右往左以四个为一组来取,每四个求一个十进制的数字,不够四个的就按那几个求就行,最后算出的数字组合起来就是十六进制。

例如:将二进制的01101011转换为十六进制

注意:16进制表示的时候前面要加0x,因此,这个16进制为0x6b

(4)16进制转换为2进制

同理,若将16进制转换为2进制,就需要将16进制的每一位数字先看成十进制,将他们依次转换为四个2进制数字。

需注意:转换后的二进制数字最前面的0要去掉。

二.原码,反码,补码

数据是以二进制的形式表示和存储的

整型——二进制形式(原码,反码,补码)

浮点型——二进制形式(浮点数的存储方式)

整数的2进制表示方法由三种,即原码,反码和补码

整数分为有符号整数和无符号整数。

有符号整数的三种表示方法均有符号位和数值位,2进制序列中,最高位的一位是被当作符号位,剩余的都是数值位。符号位都是用0表示“正”(严谨来说是非负),用1表示“负”。(口诀:0正1负

无符号整数的三种表示方法只有数值位,没有符号位,

但他们都是占32个比特位

                                                                      有符号整数

                                                                      无符号整数

                                    非负整数(它的原码,反码,补码都一样)(0也一样)

            有符号整数{

                                    负整数(它的三种表示方法各不相同)

整数{

            无符号整数(它的原码,反码,补码都一样)

负整数的原码,反码,补码

原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码

反码:将原码的符号位不变,其他位依次按位取反就可以得到反码

补码:反码+1就可以得到补码

原码得到补码也是可以使用:取反,+1的操作

补码得到原码也是可以使用:取反,+1的操作

例子:

三.操作符的分类

1.算数操作符:+,-,*,/,%

2.移位操作符:<<    >>    (只能针对整型的二进制进行操作)(计算机用补码进行移位计算)

<<:左移操作符(有*2的效果,前提是移动不能让最前面最先出现的数值“1”移出去,不然丢弃后会影响很大,*2效果微乎其微)  :左边抛弃,右边补0

注:将num移动一位后的结果赋值给了r,实际上num的值是不变的。

>>:右移操作符 (在算数右移的情况下有/2的效果):分为逻辑右移和算数右移

(1)逻辑右移:左边用0填充,右边丢弃

(2)算数右移:左边空缺的地方全都用原来该值的符号位填充,右边丢弃

       如果是正数:左边通通补0

       如果是负数:左边通通补1

C语言标准没有给出明确的规定,右移到底是采用哪种方式,最终还是取决于编译器的实现。

注意:计算机是用补码进行计算的,人是用原码计算的!因此要推测计算的的结果,要将原码变成补码进行计算!!!最后计算机打印(prinf)出来的结果是原码,所以最后还要将补码换成原码。

即计算时要先求出原码,再将它变成补码,然后将补码经过变化后再变成原码,就是它最终的值!!!每次进行这三个变换前,都要先看看它们是不是正数,如果是正数,原,反,补就都一样了(0也一样),就别再变换了,要不就错了

3.位操作符:&  |  ^  ~   (只能针对整型的二进制进行操作)

&(看0):按位与  :所对应的补码只要有一个为0则为0,两个都为1才能为1

num假设是一个随机的数字

num & 1  就可以得到num的二进制中最低位的值

比如:num & 1 == 1 ,就说明num的最低位是1

        num & 1 == 0 ,就说明num的最低位是0

例子:

|(看1): 按位或 :所对应的补码只要有一个为1则为1,两个都为0才能为0  

例子:

^:按位异或:所对应的补码相同为0,相异为1

异或是支持交换律的;任何数与0异或是它本身;两个相同的数异或是0;

例如:a^0=a   a^a=0  

          3^5^3=3^3^5=5

例子:

~:按位取反: 将所有补码都取反,符号位也取反

例子:

按位取反还可以交换两数的值,在不利用第三个数的情况下:

练习题1:如何打印出一个数字中的二进制位中有几个“1”?

方法一:

方法二:

有一个公式,若有一个数为n,则通过公式:n&(n-1),每进行一次这个公式,就可以将n的二进制中的1去掉一次

练习题2:请输入一个数,判断它是不是二的次方数

练习题3:编写代码,将13的二进制序列的第5位修改成1,然后再改回0

4.赋值操作符:=,+=,-=,*=,/=,%=,<<=,>>=,&=,|=,^=

5.单目操作符:!,++,--,&,*,+,-,~,sizeof

对于sizeof(1.当括号中有表达式的时候,是不参与计算的  2.它是计算数据类型的长度的,而非数值  3.打印 sizeof 时要用%zd打印),例如:

6.关系操作符:>,>=,<,<=,==,!=

7.逻辑操作符:&&,||(表示逻辑或)

8.条件操作符:?:

9.逗号表达式:,

逗号表达式,就是用逗号隔开的多个表达式

逗号表达式,从左往右依次执行。整个表达式的结果是最后一个表达式的结果。

例如:

10.下标引用:[ ]

11.函数调用:()

12.结构成员访问:. ,->

四.操作符的属性:优先级,结合性

几个常用的优先级

五.表达式求值:

(一).整型提升(针对所计算的类型的长度小于整型的计算

C语言中整型算术运算总是以缺省(默认)整型类型(即 int 类型)的精度来计算的,为了获得这个精度,表达式中的字符型(char )短整型( short )操作数在使用之前要被转换为 int 类型,这种转换称为整型提升。

如何进行整型提升呢?

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

2.无符号整数提升,高位补0

例如:

因此,即使时两个char类型相加,也需要先转换成int类型才能相加

整型提升的意义:

(二).算术转换(针对所计算的类型的长度大于整型的计算

如果某个操作符的各个操作数属于不同类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算数转换。

如果某个操作数的类型在上面这个列表中排名靠后,那么首先要转换为另外一个操作数的类型后执行运算。即:如果 int 类型和 double 类型进行计算,则需将 int 类型转换为 double 类型。

(三).几个有问题的表达式(不要写出这种复杂的代码)

总结:即使有了操作符的优先级和结合性,我们写出的表达式依然有可能不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在潜在风险的,建议不要写出特别复杂的表达式。不要写过于复杂的表达式,要将表达式拆的足够细,这样才能保证计算的正确性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值