欢迎光临
我们一直在努力

C语言——操作符

目录

一,操作符的分类

二,原码,反码,补码

1,定义

2,特点

3,原码,反码和补码之间的转化

三,移位操作符(<<   >>)

四,位操作符(&,|,^,~)

1,&(按位与)

2,|(按位或)

3,^(按位异或)

4,~(按位取反)

五,逗号表达式

六,函数调用和下标访问

1,下标引用操作符 [ ]

2,函数调用操作符( )

七,结构成员访问操作符

1,结构体

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

九,表达式求值

1,整型提升

2,算术转换

十,例题分析

1,求一个整数的二进制中1的个数

2,改变二进制中的某一位

3,判断一个数是否为2的次方数

十一,表达式分析

1,表达式1:

2,表达式2:

3,表达式3:

4,表达式4:

5,表达式:


一,操作符的分类

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

2,移位操作符:<<  >>

3,位操作符:&,|,^,~

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

5,单目操作符:!,++,–,&,*,+,-,~,sizeof,(类型)

6,逻辑操作符:&&,||

7,关系操作符:<,>,<=,>=,==,!=

8,条件操作符:?:

9,逗号表达式:,

10,下标引用:[ ]

11,函数调用:( )

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

二,原码,反码,补码

1,定义

整数的二进制表示方式有三种:原码,反码,补码

这三种表示方法的二进制序列都由两部分构成:符号位和数值位。其中二进制序列的第一位代表符号,‘0’表示正,‘1’表示负。剩下的位数为数值位。

特殊:0的原码,反码,补码都为00000000000000000000000000000000

原码:一个整数的32位二进制序列

例如:3的原码:00000000000000000000000000000011

反码:将原码的数值位全部取反得到的二进制序列

例如:3的反码:011111111111111111111111111111111100

补码:将反码+1得到的二进制序列

例如:3的补码:011111111111111111111111111111111101

2,特点

正整数的原码,反码,补码都相同

负整数的三者都不同

补充:整形数据在内存中存放的是对应的补码

3,原码,反码和补码之间的转化

三,移位操作符(<<   >>)

1,<<的移位规则:

左抛弃一位,右边补零

2,>>的移位规则:

1,逻辑右移:右边抛弃,左边补零(无符号整型)

2,算术右移:右边抛弃,左边保留原来该位置的数字(算术右移)

注意:两者都是对整数的补码进行操作生成补码,返回值为原码对应的数字

错误形式:不能移位一个负数

例如:a<<- 1 (这种形式是错误的)

四,位操作符(&,|,^,~)

使用注意:都是只能对整数的补码进行操作生成补码,对所有的补码二进制位进行操作,包括符号位

1,&(按位与)

使用:按照两个中有一个为0,结果就为0,两个都为1才为1的规则生成一个新的补码

2,|(按位或)

使用:按照两个中有一个为1,结果就为1,两个都为0才为0的规则生成一个新的补码

展示:

3,^(按位异或)

使用:相同为0,相异为1

展示:

运用:

不引入外部变量实现两个整形的值的交换

4,~(按位取反)

使用:对补码的每一位进行取反

展示:

五,逗号表达式

语法:

(exp1,exp2,exp3,……,expN)

从头到尾依次执行,执行的结果为最后一个表达式的结果

例子:

六,函数调用和下标访问

1,下标引用操作符 [ ]

操作数:一个数组名+一个索引值(下标)

2,函数调用操作符( )

第一个操作数是函数名,第二个操作数是函数的参数

函数调用至少有一个操作数:函数名

七,结构成员访问操作符

1,结构体

结构体是一种自定义的数据类型,可以自己创建适合的类型,结构是一些值的集合,这些值称为成员变量。结构中的每个成员可以是不同类型的变量,例如:标量,数组,指针,结构体     

结构体的声明 :

struct tag

{

      member-list;

}variable-list; };   //分号不能省略   

member-list为成员链表

结构体的嵌套:

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

在一个表达式中会有各种各样的操作符,这些操作符会有运算顺序,其运算顺序就与优先级和结合性有关。

优先级:运算符的运算优先级

结合性:当运算符的优先级相同时,就要看运算符的结合性,一般结合性按照从左到右的顺序进行运算,少数按照从右到左顺序。

主要优先级:

全部优先级:

九,表达式求值

1,整型提升

表达式中的char类型和short类型的字节大小小于int类型,在进行运算时要先转换为普通整形,再进行运算,这种转换被称为整型提升。

补充:通用CPU难以实现两个8比特位字节直接运算,所以要先转化为int类型,才能更好计算。

整型提升的规则:

1,有符号类型的提升:按照二进制的最高位的符号位来提升。

2,无符号类型的提升:高位直接补零。

例:

注意:char和short类型是否有符号是不确定的,在VS编译器中都默认为有符号的类型。

2,算术转换

当char和double类型相遇时,先将char整型提升为int,再将char算术转换为double

转换先后:

1,long double

2,double

3,float

4,unsigned long int

5,long int

7,unsigned int 

8,int

当下面的遇到上面的,下面的需要先转化为上面的再进行运算 

十,例题分析

1,求一个整数的二进制中1的个数

分析:

类比求一个整数的每一位:先对10取余数,再除以10.依次循环。

例如13   二进制最后几位为:1101

13 %2=6……1

13/2=6     6的二进制为:110

6%2=3……0  

6/2=3     3的二进制为:11

3%2=1……1

3/2=1   1的二进制为1

1%2=0   不进入循环

1/2=0  结束

注意:unsigned表示无符号整形,可以让-1对应的二进制转化为一个非常大的数的二进制。

实现求负数二进制中1的个数

第二种求法:

分析:

13二进制最后几位:001101

         1的最后几位:000001           两者&后:得到1

此时对13的二进制向右移1位:去除最右边一位的数:再次比对判读是否为一

第三种求法:

分析:n&(n-1)表达式每次能将二进制中最右侧的1去掉

例如 n:1110  n-1:1101      n&(n-1):1100

2,改变二进制中的某一位

3,判断一个数是否为2的次方数

十一,表达式分析

1,表达式1:

a*b+c*d+e*f

这个表达式的执行顺序可以是:1,a*b  2,c*d 3,e*f  4+, 5,+

                                 也可以是1,a*b  2,c*d 3,+ 4,e*f  5+

这两种表达式的运算顺序有所不同,当a,b,c,d,e,f为表达式时,里面的值相互关联,执行顺序就非常关键,不同的执行顺序会导致变量的值发生改变。

2,表达式2:

c + –c;

这个表达式是先c–在将c的值相加还是先算c再算c–然后相加,结果不得而知,这样的写法会引起歧义。

3,表达式3:

int i = 10;

i = i– – –i * ( i =
-3
) * i++ + ++i

这样写在不同的编译器里的执行结果是不同的,会引起歧义。

4,表达式4:

通过运算优先级只能确定运算顺序但不能确定函数调用的优先级,会引起歧义。

5,表达式:

int i = 1;

int ret = (++i) + (++i) + (++i);

是先算两个(++i)再相加再算一个(++i)再相加

还是先算三个(++i)再相加 

在不同的编译器中的执行结果不同,会引起歧义。

总结:即使有了运算符的优先级和结合性,仍然无法保证运算的优先顺序,此时就可能出现错误,所以我们要尽量少写复杂的运算代码,将代码的运算步骤进行拆分,更能保证运算的准确性。

赞(0)
未经允许不得转载:171主机测评 » C语言——操作符
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址