C语言的操作符

目录:

1.操作符的分类

2.二进制和进制转换

3.原码、反码、补码

4.移位操作符

5.位操作符

6.单目操作符

7.逗号表达式

8.下标访问[]、函数调用()

9.结构成员访问操作符

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

11.操作符优先级附录


1.操作符的分类

//sizeof是操作符不是函数,(类型)是指将数据强制转换
单目操作符   ! ++ -- & + - ~ sizeof() (数据类型)
算数操作符   + - * / %
赋值操作符   = += -= *= /= %= <<= >>= &= |= ^=
条件运算符   (bool)? (表达式1):(表达式2)
关系操作符   >  >= < <= == !=
逻辑运算符   && || !
移位操作符   << >>
位操作符     & | ^
下标引用     []
函数调用     ()
结构成员访问 . ->
逗号表达式   ,

上面一些基本的像算数操作符、赋值操作符、逻辑运算符、条件运算符、关系运算符、部分单目运算符我们在前面都提到过,今天我们继续介绍一部分。操作符中有一些操作符和二进制有关系,我们先铺垫一下二进制以及进制转换的知识。 

2.二进制和进制转换

其实我们经常能听到 2进制、8进制、10进制、16进制 这样的讲法,那是什么意思呢?

其实2进制、8进制、10进制、16进制是数值的不同表⽰形式⽽已。

⽐如:数值15的各种进制的表⽰形式:

1  15的2进制:1111
2  15的8进制:17
3  15的10进制:15
4  15的16进制:F
5  
6   //16 进制的数值之前写: 0x
7   //8 进制的数值之前写: 0

2.1 进位计数制

基本概念:

数制:是人们对数量计数的一种统计规律。其计数方法是把数划分为不同的数位,当某一位累计一定数量之后,向高位进位,该位又从零开始。进位计数制可以用少量的数码表示较大的数。因而广泛采用。在这种计数制中,同一个数码在不同的数位上所表示的数值不同。

基本要素:进位基数和数位的位权

基数:计数制中使用的数码个数称为该位进位计数制的进位基数,记作R。一般而言R进位制的基数为R,就有R个数码。

位权:不同数位上的固定常数,称为该数位的位权值,简称:“位权”。用Ri 表示,R为进位基数, i 是各数位的序号。按如下方法确定。

整数部分:以小数点为起点,自右向左依次为 0,1,2,.… n-2,n-1.

小数部分:以小数点自左向右为  -1,-2,-3,…,-m

R 进制的数表示为:

730c03c4e65841c2bcb4931ada5da5d0.png

   十进制是人们最熟悉的数制,但机器实现十分困难!目前数字系统均是采用二进制,是机器唯一认识的数码。但书写太长易出错,为此引入八进制与十六进制的概念

2.2 过渡进制

八进制

 “逢八进一”。具有0,1,2,3,4,5,6,7,八个代码。由于23=8,所以三位二制数可用一位八进制数表示。其长度压缩至二进制长度的1/3,八进制与二进制关系如表1 所示。

十六进制

 “逢十六进一”。具有0 ~9;A~F十六个代码。由 于2 4=16,所以四位二进制 数可用一位十六进制数表示, 其长度压缩至二进制长度的 1/4,十六进制与二进制关系 如表2 所示d2b42a4b618e4504a3a3bbc37973fa95.pngd870b9b199d247d5a6f3f8f82e2d1882.png

 

 

64340b851b66486d8d7ec308db7db947.png

 

/*

例一:
  (10101.11)B =1×2^4+1×2^2+1×2^0+1×2^-1+1×2^-2 
                =16+4+1+0.5+0.25
                =(21.75)D
例二:
    (165.2)o =1×8^2+6×8^1+5×8^0+2×8^-1
               =64+48+5+0.25      
               =(117.25)D
例三:

     (2A.8)H  =2×16^1+10×16^0+8×16^-1 
                =32+10+0.5
                =(42.5)D
*/

2.3 二进制转十进制

二进制最先由德国德国自然科学家、数学家、唯心主义哲学家莱布尼茨所发明

 

最早蕴含着二进制规律的思想出现在《周易系辞下转》的八卦图中

 

八卦中的每一个卦,由称为“爻”的两种符号排列而成。“――”叫做“阴爻”,相当于二进制里的0,“—”叫做“阳爻”,相当于二进制中的1,则八个方位上的八卦符号与三位二进制编码有唯一的对应关系

那我们就重点介绍⼀下⼆进制: 

⾸先我们还是得从10进制讲起,其实10进制是我们⽣活中经常使⽤的,我们已经形成了很多尝试:

• 10进制中满10进1

• 10进制的数字每⼀位都是0~9的数字组成

其实⼆进制也是⼀样的

• 2进制中满2进1  

• 2进制的数字每⼀位都是0~1的数字组成

那么 1101 就是⼆进制的数字了。

8df4e01d603c4ca5a9f7d3479dc3fec5.png

我们通常借助BCD编码的思想来进行十进制和二进制互换。例如25=16+8+1,则25对应的二进制码为11001. 

3.原码、反码、补码

3.1原码

a9da328141b047bda371e4888e26df63.png

acfcd12db8e4478388652fb611b04849.png 

Tips: 原码其实就是十进制对应的二进制数

3.2反码 

86b01cfeba1348469e56d8fa64e0e706.png

 6a12f7f0e19a41c4bd4819d630fc0bbb.png

 Tips:负数快速求反码:将真值的数值位按位取反!最高位为符号位,不变。正数没有补码,或说补码是原码本身

3.3补码

补的概念:时钟的顺逆时针转动。6-3=3;6+9-12=3;(-12是因为时钟以12为模)。由此可见-3可用+9代替,减法就变成了加法。此时称+9是-3以12为模的补数。记作 -3 三 +9 (mod 12)

63a9ff3136c04e0881129051e90de201.png

9c50b402eec4466483a7ea72bc905052.png 

结论:一个负数加上“模”即得该负数的补数。一个负数和它的补数绝对值之和即为模数。正数的补数即是本身

 Tips:补码其实就是反码末位+1,由于正数没有补码,在这里我们可以得出结论:正数原反补三码一致。

3.4拓展

对于整形来说:数据存放内存中其实存放的是补码。 为什么呢?

在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀ 处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算 过程是相同的,不需要额外的硬件电路。
 

4.移位操作符

Tips:移位操作符的操作数只能是整数。

左移位符

<<移位规则:

左边抛弃,右边补0

右移位符

>>移位规则:

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

算数右移:左边用该值的符号位填充,右边丢弃

#include <stdio.h>
int main()
{
    int num=10;
    int n=num>>1;//警告:移动位数不可为负,这是未定义的即不可为int n= num >> -1
    printf("n=%d\n",n);
    printf("num=%d\n",num);
    return 0;
}

 

5.位操作符

Tips:位操作符的操作数只能是整数。

&          // 按位与
|           // 按位或
^          // 按位异或
~         // 按位取反

 直接上代码:

#include <stdio.h>
int main()
{
     int num1 = -3;
     int num2 = 5;
     printf("%d\n", num1 & num2);
     printf("%d\n", num1 | num2);
     printf("%d\n", num1 ^ num2);
     printf("%d\n", ~0);
     return 0;
}

一道变态的面试题:

 不能创建临时变量(第三个变量),实现两个整数的交换。

#include <stdio.h>
int main()
{
     int a = 10;
     int b = 20;
     a = a^b;
     b = a^b;
     a = a^b;
     printf("a = %d b = %d\n", a, b);
     return 0;
}

 

6.单目操作符

单⽬操作符有这些:!、++、--、&、*、+、-、~ 、sizeof、(类型)

 

单⽬操作符的特点是只有⼀个操作数,在单⽬操作符中只有 & 和 * 没有介绍,这2个操作符,我们放在 学习指针的时候学习。

7.逗号表达式

exp1, exp2, exp3, …expN  

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

逗号表达式,从左向右依次执⾏。整个表达式的结果是最后⼀个表达式的结果。

//代码1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
c是多少?

//代码2
if (a =b + 1, c=a / 2, d > 0)

//代码3
a = get_val();
count_val(a);
while (a > 0)
{
 //业务处理
 //...
 a = get_val();
 count_val(a);
}
改写为逗号表达式
while (a = get_val(), count_val(a), a>0)
{
 //业务处理
}

 

8.下标访问[]、函数调用()

8.1下标应用操作符[ ]

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

int arr[10];
arr[9]=9;//实⽤下标引⽤操作符。
//[ ]的两个操作数是arr和9。

8.2函数调用操作符( )

接受⼀个或者多个操作数:第⼀个操作数是函数名,剩余的操作数就是传递给函数的参数。

#include <stdio.h>
void test1()
{
 printf("hehe\n");
}
void test2(const char *str)
{
 printf("%s\n", str);
}
int main()
{
 test1(); //这⾥的()就是作为函数调⽤操作符。
 test2("hello bit.");//这⾥的()就是函数调⽤操作符。
 return 0;
}

9.结构成员访问操作符

讲结构体那块再说。

10.操作符的属性:

优先级

优先级指的是,如果⼀个表达式包含多个运算符,哪个运算符应该优先执⾏。各种运算符的优先级是不⼀样的。

常见优先级顺序:

• 圆括号( () )
• ⾃增运算符( ++ ),⾃减运算符( -- )
• 单⽬运算符( + 和 - )
• 乘法( * ),除法( / )
• 加法( + ),减法( - )
• 关系运算符( < 、 > 等)
• 赋值运算符( = )

结合性

如果两个运算符优先级相同,优先级没办法确定先计算哪个了,这时候就看结合性了,则根据运算符是左结合,还是右结合,决定执⾏顺序。⼤部分运算符是左结合(从左到右执⾏),少数运算符是右 结合(从右到左执⾏),⽐如赋值运算符(=)

 

即使有了操作符的优先级和结合性,我们写出的表达式依然有可能不能通过操作符的属性确定唯⼀的 计算路径,那这个表达式就是存在潜在⻛险的,建议不要写出特别复杂的表达式


操作符优先级附录

 

优先级

运算符

名称或含义

使用形式

结合方向

说明

1

[]

数组下标

数组名[常量表达式]

左到右

--

()

圆括号

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

--

.

成员选择(对象)

对象.成员名

--

->

成员选择(指针)

对象指针->成员名

--

(type){list}复合字面量(C99)(type){变量列表}--

2

-

负号运算符

-表达式

右到左

单目运算符

~

按位取反运算符

~表达式

++

自增运算符

++变量名/变量名++

--

自减运算符

--变量名/变量名--

*

取值运算符

*指针变量

&

取地址运算符

&变量名

!

逻辑非运算符

!表达式

(类型)

强制类型转换

(数据类型)表达式

--

sizeof

长度运算符

sizeof(表达式)

--

_Alignof对齐要求(C11)_Alignof(type)--

3

/

表达式/表达式

左到右

双目运算符

*

表达式*表达式

%

余数(取模)

整型表达式%整型表达式

4

+

表达式+表达式

左到右

双目运算符

-

表达式-表达式

5

<< 

左移

变量<<表达式

左到右

双目运算符

>> 

右移

变量>>表达式

6

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

小于

表达式<表达式

<=

小于等于

表达式<=表达式

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

8

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

表达式1?

表达式2: 表达式3

右到左

三目运算符

14

=

赋值运算符

变量=表达式

右到左

--

/=

除后赋值

变量/=表达式

--

*=

乘后赋值

变量*=表达式

--

%=

取模后赋值

变量%=表达式

--

+=

加后赋值

变量+=表达式

--

-=

减后赋值

变量-=表达式

--

<<=

左移后赋值

变量<<=表达式

--

>>=

右移后赋值

变量>>=表达式

--

&=

按位与后赋值

变量&=表达式

--

^=

按位异或后赋值

变量^=表达式

--

|=

按位或后赋值

变量|=表达式

--

15

逗号运算符

表达式,表达式,…

左到右

--

 


感谢观看!

 

  • 23
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值