关于这一章节的东西,也是学编程的一个很基础的东西,每个语言也都会有,这里记录一些比较重要的知识点,好了进入正题:
运算符可以有如下几种分法:
下面对其一一进行学习:
算术运算符:
① ++和--运算符前置和后置有很大区别
![](http://images0.cnblogs.com/blog/324374/201311/24151119-98ca92d04c164e1db1f1443ab531cf88.png)
运行结果:
理解:
对于表达式,需知道它对应于一个唯一的值,而++i和i++都属于表达式,对于i++的值可以这样理解:
int tmp = i; i = i+1; return tmp;
而对于++i表达式的值,实际上就是改变的i的值:
i = i+1; return i;
②类型转换:
运算符的操作数属于不同的数据类型,运算时通常会将这些操作数转换为同一类型,由编译系统自动完成
在赋值表达式中,自动将赋值运算符右边表达式的值的类型转换成左边变量的类型
级别高低:char->short->int->long->float->double->long double,由低级别的自动转化成高级别的类型。
下面用一个表达式的计算过程图能清晰的表达类型转换的意义:
![](http://images0.cnblogs.com/blog/324374/201311/24154145-6dd7d2438cde43c7ae009db4727adb3d.png)
③优先级:
![](http://images0.cnblogs.com/blog/324374/201311/24154955-b6b61bd0bc0542c5b251501ea0853162.png)
![](http://images0.cnblogs.com/blog/324374/201311/24155423-b772e273cfcb4e3ea807512f0d666c4e.png)
运行结果:
![](http://images0.cnblogs.com/blog/324374/201311/24155507-5a65c6470a154a04a661b16df11304bf.png)
这个比较容易理解,而对于一元运算符的优先级呢?这里举一个例子:
*p++
因为*、++是同级别的运算,所以这时按结合性来计算,而它属于一元,是按从右到左的顺序:
![](http://images0.cnblogs.com/blog/324374/201311/24155933-f1629997bb414f7c86d89a502aea4eae.png)
所以:
*p++ = *(p++) != (*p)++
赋值运算符:
赋值运算符的优先级低于算术运算符,仅高于逗号运算
![](http://images0.cnblogs.com/blog/324374/201311/24160529-04e88bba9b424ad69156546762036c71.png)
关系运算符:
在c语言中没有布尔类型,0表示假,1表示真:
![](http://images0.cnblogs.com/blog/324374/201311/24160944-2d4def2a76654704a8f43748e0bd71b9.png)
逻辑运算符:
![](http://images0.cnblogs.com/blog/324374/201311/24161246-d5dff9fe56bc4a189771c1cbe5a23078.png)
下面来看两个例子:
![](http://images0.cnblogs.com/blog/324374/201311/24162348-e8884411563f4dc1a8ad59ea57f5a562.png)
说明:
1、++算术运算符比逻辑运算符||、&&优先级要高
2、&&优先级要与||高
3、由于||如果左边值为true,则会短路,所以++x=1,为逻辑真了,所以||右边的表达式就没有计算了。
![](http://images0.cnblogs.com/blog/324374/201311/24162605-4177ff195f0e4e6690a472a17d51861f.png)
说明:
1、(++x||++y)有短路,所以++y并没有计算,
2、&&如果左边为false,则也会短路,而由于上面表达式中为true,所以,++z会执行到。
位运算符:
将数字转换成二进制形式后再按位处理
![](http://images0.cnblogs.com/blog/324374/201311/24163208-2bea3a87fe284495b5e09a1063ba5065.png)
其中说明一下右移操作:
![](http://images0.cnblogs.com/blog/324374/201311/24163535-6d23118b8c794e4a9b6408118c079421.png)
![](http://images0.cnblogs.com/blog/324374/201311/24164112-b8fac1a87d8b4138ab0904f835cf7beb.png)
运行结果:
![](http://images0.cnblogs.com/blog/324374/201311/24164213-f29c2c1a709740a5a7552c9449f57f4c.png)
以十六进制的形式输出:
![](http://images0.cnblogs.com/blog/324374/201311/24164338-e96b97ce46f64d5fa6e964e03424f6cc.png)
运行结果:
![](http://images0.cnblogs.com/blog/324374/201311/24164432-82b9a299ac61482698ef55d60423ef2a.png)
为了让十六进制更加清晰,前面加一个ox前缀:
![](http://images0.cnblogs.com/blog/324374/201311/24164657-e5f5156d8a7348f7904465f884b48ec1.png)
输出如下:
![](http://images0.cnblogs.com/blog/324374/201311/24164753-6857cb82d5a54542989eb19ffa33e668.png)
这时,将它往右移8位
![](http://images0.cnblogs.com/blog/324374/201311/24165055-9dcd40c0c8194f20b1339ee72d139ad6.png)
![](http://images0.cnblogs.com/blog/324374/201311/24165138-f2ee37c7573f443b8e0b317b33b1b069.png)
分析:
![](http://images0.cnblogs.com/blog/324374/201311/24165817-9aeb9def3bed4a8aac7d806772aefd0b.png)
如果是有符号数,那又是怎么样的呢?
![](http://images0.cnblogs.com/blog/324374/201401/01151521-45797ba29ea94c11b774ba5c86dc539f.png)
![](http://images0.cnblogs.com/blog/324374/201401/01151728-2c22b093017f432e86f6f6ed172d4869.png)
C语言中的右移分为逻辑右移和算术右移:
逻辑右移:高位补0(对于无符号数来说,>>是指逻辑右移)
算术右移:保留符号位不变(对于正数,高位补0;对于负数,高位补1)
实际上,C语言并没有规定有符号数的>>是逻辑右移还是算术右移,但是,几乎所有的编译器将有符号数的>>都实现成了算术右移了。
知道了上面的位运算,下面用一个实际例子,来将其运用一下:
![](http://images0.cnblogs.com/blog/324374/201401/01152831-0b2eebe7e7bd4dd3bfc1626da644fa8c.png)
![](http://images0.cnblogs.com/blog/324374/201401/01152916-4953c546254a4cbda002c1dca638b405.png)
![](http://images0.cnblogs.com/blog/324374/201401/01153349-f03100a10c614ab2971205e2edede272.png)
![](http://images0.cnblogs.com/blog/324374/201401/01153456-f0574f742e364d479c78986431ac1645.png)
【说明:x >> 8 & 0xFF,为什么还要与上0xFF,是为了有可能是算术右移,高位补1(虽说我们这个例子符号位是0),所以这样是为了保证将高八位全去掉】
下面举一些位运算的例子:
![](http://images0.cnblogs.com/blog/324374/201401/01153825-7a1cf7395dc3451288716321768e51e8.png)
其中~10为什么是-11呢,原因如下:
![](http://images0.cnblogs.com/blog/324374/201401/01155254-4fe84ed91a3c4e88aa52c47447b4f481.png)
位运算符优先级:
![](http://images0.cnblogs.com/blog/324374/201401/01155545-e0df750ae5c14f29a04c997805d384b0.png)
位运算示例【这个在实际当中都会用到的,争取要记住】:
![](http://images0.cnblogs.com/blog/324374/201401/01155728-6169504d19da46a4b11805fcc69f37e3.png)
![](http://images0.cnblogs.com/blog/324374/201401/01160223-2b82444209984d429cf78701a92e0c1d.png)
![](http://images0.cnblogs.com/blog/324374/201401/01160348-16c5d50167684f99966e1f0a50759a99.png)
![](http://images0.cnblogs.com/blog/324374/201401/01160638-eadf0fda68a24bdf843ca43f54d32fd2.png)
解析:
![](http://images0.cnblogs.com/blog/324374/201401/01161218-c6abb732c60d48a09aff46c4c5577945.png)
下面这两个位操作,是会经常用到的【重要】
![](http://images0.cnblogs.com/blog/324374/201401/01162141-c6465853f8f9445790f31b15b0a1d75e.png)
关于这两个位运算的应用,在博文:http://www.cnblogs.com/webor2006/p/3500354.html有用到,一般是用来设置状态,并清除状态
![](http://images0.cnblogs.com/blog/324374/201401/01162432-50b5bbd7f13d4fe1aa83d3d95745f68c.png)
这个也是上面提到过的,下面我们来论证一下该等式:
![](http://images0.cnblogs.com/blog/324374/201401/01164857-18f9976c517d4a22b142942dd4abddb3.png)
上面这是求一个正数的取反操作,那如果对一个负数进行取反,该等式也成立么,先用代码看下结果:
![](http://images0.cnblogs.com/blog/324374/201401/01165539-90fbcba4ebe14227ae658bcdf9c688b6.png)
![](http://images0.cnblogs.com/blog/324374/201401/01165800-6ec1eb8cb0194722b958783811708020.png)
下面关于运算符的优化级进行一个总结:
![](http://images0.cnblogs.com/blog/324374/201401/01205438-63f8ea79b01d47ed8669ca4f9c8b4fba.png)
![](http://images0.cnblogs.com/blog/324374/201401/01205509-c63430f5d9a2481b8024bfdaa7ad786b.png)
下面对所有运算符的优化级进行一个总结,以便之后对优化级有疑惑时来进行查找:
![](http://images0.cnblogs.com/blog/324374/201401/01205831-c372d847fef3403ea11c0e06ac3374b4.png)
![](http://images0.cnblogs.com/blog/324374/201401/01205903-9f6b3dbf672147c6a00fa0370b2424a0.png)
![](http://images0.cnblogs.com/blog/324374/201401/01210037-9e286a5724df426d8f032c33a6d275f1.png)
以一个范例来说明一下优先级:
![](http://images0.cnblogs.com/blog/324374/201401/01210436-a616c31213e34ce8ab3595ef6a183b20.png)
修改优先级:
![](http://images0.cnblogs.com/blog/324374/201401/01211412-58dea5143d7b4c199131275c4bde0aaa.png)
下面来使用一下三目及逗号运算符:
![](http://images0.cnblogs.com/blog/324374/201401/01211814-4e2a2ae5a61e4e39a74a1f0a383f8e3f.png)
编译运行:
![](http://images0.cnblogs.com/blog/324374/201401/01211850-09857d27eefc442480576d4f4411fc52.png)
【注意:printf("%d\n",1,2,3);并非是逗号表达式,而是函数的参数传递】
常见的一些优先级错误:
![](http://images0.cnblogs.com/blog/324374/201401/01212049-6c0449a7f1864333b8e2c5f097b7c50d.png)
【建议:关于表达式的优级,只要把握“算术运算符优先级高于关系运算符高于逻辑运算符高于赋值运算符"原则,并记住上面经常范的错误,就能搞定它了!】