WHCSRL 技术网

C语言运算符分析(带你系统了解C语言中涉及的运算符)

自学C语言很长一段时间了,而里面很多运算符都感觉在脑中模模糊糊的,今天在这里系统的总结下C语言的运算符,一方面希望能巩固我所学的东西,另一方面希望能带给你们一些帮助,如果下面有什么不足的地方敬请指正,希望我们能共同进步。


一.运算符分类

1.算术运算符(用于各类数值运算)

常见的有:

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

%%  (求余,又称模运算)  注意负数的求余(如(-5)%%6==-5,(-12)%%5==-2)

++ (自加)     

注意:a++与++a的区别       a++和++a都是将a的值+1再赋给a,但是a++和++a所代表的值不一样,(a++)的值为a的原值,而(++a)的值为a+1;如a变量原值为0,则(a++)==0;而(++a)==1

--    ( 自减)       其与自加相同


2.关系运算符  (用于比较运算)

常见的有:

>      <       ==(注意是两个=)       >=        <=            !=(不等于)


3.逻辑运算符  (用于逻辑运算)

&&(与)                    ||(或)          !(非)

说明:若事件A和B,则(A&&B)的值在A和B都成立的时候为1,否则为0;(A||B)的值在A和B都为假时为0,其余都为1。


4.位操作运算符     (参与运算的量,按二进制进行运算)

位与(&)

对二进制的数进行位运算     只有两个同时为1时位与(&)的值才为1,否则位0,而且是一位一位的额进行比较的          如十进制4和3         

4的二进制00000100
3的二进制00000011
4&300000000

              所以最后的结果为0

与运算的特殊作用

           (1)清零。如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。
           (2)取一个数中指定位
方法:找一个数,对应X要取的位,该数的对应位为1,其余位为零,此数与X进行“与运算”可以得到X中的指定位。
例:设X=10101110,
取X的低4位,用 X & 0000 1111 = 0000 1110 即可得到;
还可用来取X的2、4、6位。

            (3)判断一个数的指定为是否为1

方法:若想要判断X的第四位是否为1,这将X与一个第四位为1,其他为0的数进行位与(&)运算,若值为0,则的四位值不为1。

位或(|) 

位或(|)运算规则大致与位与(&)相同,但 位或(|)只有当两个都为0时其值才为0,其它都为1。

或运算”特殊作用:

                      常用来对一个数据的某些位置1。

       方法:找到一个数,对应X要置1的位,该数的对应位为1,其余位为零。此数与X相或可使X中的某些位置1。 

       例:将X=10100000的低4位置1 ,用 X | 0000 1111 = 1010 1111即可得到。

位非(~)(取反运算符)(参加运算的一个数据,按二进制位进行“取反”运算。

运算规则

对一个数的二进制取反,1变为0,0变为1。

如:~1=0;   ~0=1;

位异或(^)   

运算规则

  • 运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0;

    • 即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。
  • 例如:10^-9 即 0000 1010 ^ 1111 0111 = 1111 1101(补码) 原码即为1000 0011 即10^-9 = -3

*(注意补充:原码  反码  补码

原码            机器只能读存二进制的数,原码就是这个数的二进制数,其最高位表示符号,其中1                       表示负数,0表示正数。

反码            正数的反码和原码相等,而负数的反码除最高位表示正负符号的1不变,其他的每一                       位上1变为0,0变为1。

补码            正数的补码的原码相等,而负数的补码则是在反码的基础上+1,如:-3

原码10000011
反码11111100
补码11111101

  (至于详细的内容就不在这里提了,想要了解其中的原理的,如为什么补码要加一,自己去找那些大神的详细解说)

             

“异或运算”的特殊作用:

(1)使特定位翻转 找一个数,对应X要翻转的各位,该数的对应位为1,其余位为零,此数与X对应位异或即可。

  • 例:X=10101110,使X低4位翻转,用X ^ 0000 1111 = 1010 0001即可得到。

(2)与0相异或,保留原值 ,X ^ 0000 0000 = 1010 1110。

(3)交换a和b

方法一方法二
1.a=a^b1.a= a-b
2.b=b^a2.b= a+b
3.a=a^b3.a= b-a

左移(<<)

将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。

  • 例:a = a << 2 将a的二进制位左移2位,右补0,

  • 左移1位后a = a * 2;

  • 若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。

右移(>>)

将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。

  • 例如:a = a >> 2 将a的二进制位右移2位,
    • 左补0 or 补1 得看被移数是正还是负。
  • >> 运算符把 expression1 的所有位向右移 expression2 指定的位数。expression1 的符号位被用来填充右移后左边空出来的位。向右移出的位被丢弃。

    • 例如,下面的代码被求值后,temp 的值是 -4:
      var temp = -14 >> 2
      -14 (即二进制的 11110010)右移两位等于 -4。

5.赋值运算符        (用于赋值运算)

简单赋值(=)

复合算术赋值(+=,-=,=,/=,%%=)

复合位运算赋值(&=,|=,^=,>>=,<<=)

这里就不再展开了,这里因该没什么难理解的地方


6.条件运算符      

?:(三目运算符)

常见型式

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

理解:如果表达式1为true,则整个表达式的值为 表达式2的值(即,冒号左边的值);
           如果表达式1为false,则整个表达式的值为 表达式3的值(即,冒号右边的值);

注意:表达式2,3只会运行一个,至于运行的是哪一个要看表达式1是否成立


7.逗号运算符            用于把若干表达式组合成一个表达式(,)

一般形式:

表达式1,表达式2
  • 1

注意事项:

  1. 逗号运算符是C语言运算符中优先级最低的运算符
  2. 结合方式:自左至右

逗号表达式的求解过程是:先求解表达式1,再求解表达式2。整个逗号表达式的值是表达式2的值


8.指针运算符                用于取内容(*)和取地址(&)二种运算。


9.求字节数运算符     sizeof

注意:sizeof(数组名),其中的数组名代表整个数组。

补充:

数组名代表整个数组的两个中情况

1. sizeof(数组名)

2. &数组名


10.特殊运算符    有

括号()

下标[]

arr[3]=*(arr+3)

成员(→,.)

很多时候容易把->和.搞混淆了,下边为他们的区别:

一般情况下用“.”,只需要声明一个结构体。格式是,结构体类型名+结构体名。然后用结构体名加“.”加域名就可以引用域 了。因为自动分配了结构体的内存。

而用“->”,则要声明一个结构体的指针,还要手动开辟一个该结构体的内存,然后把返回的指针给声明的结构体指针,才能用“->”正确引用。否则内存中只分配了指针的内存,没有分配结构体的内存,导致想要的结构体实际上是不存在。这时候用“->”引用自然出错了,因为没有结构体,自然没有结构体的域了。

此外,(*a).b 等价于 a->b

补充:

1、单目运算符:

  只对一个变量进行操作。

  a++;

2、双目运算符:

  对两个变量进行操作;

  a=1; b=3; c=a+b;就是双目运算符;

3、三目运算符:

  对三个变量进行操作;



二.运算符的优先级。

上图出自《c陷阱与缺陷》中的一图

运算优先级最高的是前述运算符(如函数的调用)。仅次于前述运算符的是单目运算符,在真正意义上的运算符中,它们的优先级最高(注意:类型转换也是单目运算符,它的优先级和其他单目运算符优先级一样)并且单目运算符是自右至左结合的

优先级比单目运算符要低的,接下来就是双目运算符。在双目运算符中,算数运算符(+ - * / %%)的优先级最高,移位运算(<<   >>)符次之,关系运算符(>    <    <=    >=)再次之,接着是逻辑运算符赋值运算符,最后是条件运算符(三目运算符)

1.任何一个逻辑运算符的优先级低于任何一个关系运算符。

2.移位运算符的优先级比算数运算符要低,但是比关系运算符要高 

同一类型运算符的相对优先级

        乘法除法求余优先级相同,加法减法优先级相同,两个移位运算符优先级相同。

        但是六个关系运算符优先级并不相同,运算符==和!=的优先级要低于其他四种运算符的优先级

        任何两个逻辑运算符的优先级不同,所有按位运算符要比顺序运算符的优先级高,每个“与”运算符要比“或”运算符的优先级要高,而按位异或的优先级则是位与按位与和按位或之间。

通过以上的规律和图表来记运算符的优先级就会显得非常轻松了!

        


 

推荐阅读