Chinaunix首页 | 论坛 | 博客
  • 博客访问: 711611
  • 博文数量: 96
  • 博客积分: 2110
  • 博客等级: 大尉
  • 技术积分: 1018
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-23 19:36
文章分类

全部博文(96)

文章存档

2013年(2)

2012年(17)

2011年(77)

分类: C/C++

2011-02-22 18:47:52

在看一些字符串问题的时候,经常出现这样的语句, *tmp++ = *p;比如tmp和p是指向数组元素的指针,那么这个语句的执行顺序是怎样的呢?正确的理解是*tmp,将*p赋给*tmp后tmp++。但是我不是很理解,*和++优先级是一样的。那么在=左边是从左到右执行,先*tmp后tmp++,那么*p是赋给++后还是++前呢??

楼主,您应该好好了解下,优先级,结合方向,执行顺序。这写都是不同的。
  ++ *虽然优先级一样,但它是右结合的。故*temp++  等价于*(temp++),而不是(*temp)++  。优先级是相对于不同类型运算符而言,结合方向是相对于同一优先级的不同或相同运算符而言。但执行顺序和上面两者无明显关系。*temp++   = *p是无法确定先计算等号左边还是右边,甚至同时计算。c标准是没有严格规定,也完全没必要规定,会影响代码执行效率。把这个问题完全解释清楚,也不是三言两语能讲明白,如果您还有什么疑问,再提出来。

以上更清楚的写法:((*(temp++)) = (*p))

! ~ ++ -- + - * & 强制类型名 sizeof ?: = += -= *= /= %= =&= ^= |= 《=  》= 

是自右向左的,其他都是自作向右
自右向左:左结合

圆下箭头一顿号
非凡增减富强针地长(星地长,比较好记)
三乘除,四加减,五移位
千万别把鱼忘记,它在盛饭的厨子里
小灯大灯灯灯不等
爸喂鱼,舅疑惑,裸鸡也疑惑
十三姨,十四父,十五逗,兜到低


圆下箭头一顿号” 指的是第1级的运算符。其中圆指的是运算符(),下指的是下标运算符[],箭头指的
是指向结构体成员运算符->,顿号指的是结构体成员运算符、
非凡增减富强针地长” 指的是第2级的运算符。其中非指的是逻辑运算符!,凡指的是按位取反运算符
~,增减指的是自增和自减运算符++和--,富指的是负号运算符-,强指的是类型转换运算符(类型),针
指的是指针运算符*,地指的是地址运算符&,长指的是长度运算符Sizeof
三乘除,四加减,五移位” 指的是第3级到第5级的运算符。其中三四五并无实际意义,只是起区分级
别而已。也可以想象三指的是第13级运算符。乘除指的是乘法运算符*和除法运算符/,加减指的是加法运
算符+和减法运算符-,移位指的是左移运算符<<和右移运算符>>
千万别把鱼忘记,它在盛饭的厨子里”指的是求余运算符%,它位于盛饭的厨子里,即指和乘法运算符、
除法运算符在一起。
小灯大灯灯灯不等” 指的是第10级到第9级的运算符。其中小灯大灯指的是关系运算符<、<=、>和
>=,灯灯指的是等于运算符==,不等指的是不等于运算符!=
爸喂鱼,舅疑惑,裸鸡也疑惑”指的是第8级到第12级的运算符。其中,爸喂鱼之指的是第8级的按位与
运算符&,舅疑惑指的是第7级的按位异或运算符^和第6级的按位或运算符||,裸鸡也疑惑指的是第5级、
第4级的逻辑与运算符&&和逻辑或运算符||
十三姨,十四父,十五逗,兜到低”指的是第13级到第15级的运算符。其中,十三姨指的是条件运算
符?: (三有双重含义,即指?:的优先级别是三,它的运算符类型也是三目,?难道不是姨即疑惑吗?),
十四父的十四没有实际意义,父指的是赋值运算符=、+=、-=、*=、/=、%=、>>=、<<=、&=、^=
和|= ,十五逗指的是第1级的运算符,兜到低指的是15级运算符以,结束。

附录:C语言运算符及优先级
优先级         运算符         含义                   运算符类型        结合方向
1         ()         圆括号                             单目            自左向右
         []         下标运算符                
         —>         指向结构体成员运算符                
         、         结构体成员运算符               
2         !         逻辑非运算符                                         自右向左

         ~         按位取反运算符                
         ++         自增运算符                
         --         自减运算符                
         -         负号运算符                
         (类型)         类型转换运算符                
         *         指针运算符                
         &         地址运算符                
         Sizeof         长度运算符                
3         *         乘法运算符                             双目           自左向右
         /         除法运算符                
         %         求余运算符                
4         +         加法运算符                
         -         减法运算符                
5         <<         左移运算符                
         >>         右移运算符                
6         <、<=、>、>=         关系运算符                
7         ==         等于运算符                
         !=         不等于运算符                
8         &         按位与运算符                
9         ^         按位异或运算符                
10         |         按位或运算符                
11         &&         逻辑与运算符                
12         ||         逻辑或运算符                
13         ?:         条件运算符                           三目           自右向左

14         =、+=、-=、*=、
            /=、%=、>>=、
            <<=、&=、^=、|=    赋值运算符          双目        
15         ,         逗号运算符                               双目          自左向右


括号成员第一;         //括号运算符[]() 成员运算符.   ->
全体单目第二;         //所有的单目运算符比如++ -- +(正) -(负) 指针运算*&
乘除余三,加减四;    //这个"余"是指取余运算即%
移位五,关系六;     //移位运算符:<< >> ,关系:> < >= <= 等
等于(与)不等排第七;     //即== !=
位与异或和位或;     //这几个都是位运算: 位与(&)异或(^)位或(|)     
"三分天下"八九十;  
逻辑或跟与            //逻辑运算符:|| 和 &&
十二和十一;        //注意顺序:优先级(||)   底于 优先级(&&)
条件高于赋值,    //三目运算符优先级排到 13 位只比赋值运算符和","高//需要注意的是赋值运算符很多!
逗号运算级最低!    //逗号运算符优先级最低

由于C语言的运算符优先级与C++的不完全一样(主要是增加了几个运算符),所以这个口诀不能完全实用于
C++.但是应该能够兼容,大家可以比较一下他们的区别应该就能够很快掌握C++的优先级的!

醋坛酸味灌
味落跳福豆

共44个运算符

-初等,4个: ( ) [ ] -> 指向结构体成员 . 结构体成员
-单目,9个: ! ~ ++ -- -负号 (类型)   *指针 &取地址 sizeof长度 (结合方向:自右向左)
-算术,5个: * / % + -减
-位移,2个: << >>
-关系,6个: < <= > >= == 等于 != 不等于
-位逻,3个: & 按位与 ^ 按位异或 | 按位或
-逻辑,2个: && 逻辑与 || 逻辑或
-条件,1个,三目: ? :                                                         (结合方向:自右向左)
-赋值,11个: = += -= *= /= %= >>= <<= &= ^= |=         (结合方向:自右向左)
-逗号,1个: ,
结合方向自右向左的只有三类:赋值、单目和三目,其它的都是从左至右结合。


注意:自己今天写程序时候把关系运算符号和位逻辑的优先级弄反。尽量用括号,就不出问题。
如:if(P1OUT&BIT0==0)P1OUT ^=BIT0; //判断p1.0是否输出为0,是就翻转,即点亮LED.
这行程序是错误的。可两边加上括号,即if((P1OUT&BIT0)==0),或是直接用:P1OUT|=BIT0;

具有最高优先级的其实并不算是真正的运算符,它们算是一类特殊的操作。()是与函数相关,[]与数组相
关,而->及.是取结构成员。
其次是单目运算符,所有的单目运算符具有相同的优先级,因此在我认为的 真正的运算符中它们具有最高
的优先级,又由于它们都是从右至左结合的,因此*p++与*(p++)等效是毫无疑问的。
接下来是算术运算符,*、/、%的优先级当然比+、-高了。
移位运算符紧随其后。
其次的关系运算符中,< <= > >=要比 == !=高一个级别,不大好理解。
所有的逻辑操作符都具有不同的优先级(单目运算符出外,!和~)
逻辑位操作符的"与"比"或"高,而"异或"则在它们之间。
跟在其后的&&比||高。
接下来的是条件运算符,赋值运算符及逗号运算符。

在C语言中,只有4个运算符规定了运算方向,它们是&&、| |、条件运算符及赋值运算符。
&&、| |都是先计算左边表达式的值,当左边表达式的值能确定整个表达式的值时,就不再计算右边表达式
的值。如 a = 0 && b; &&运算符的左边位0,则右边表达式b就不再判断
在条件运算符中。如a?b:c;先判断a的值,再根据a的值对b或c之中的一个进行求值。
赋值表达式则规定先对右边的表达式求值,因此使 a = b = c = 6;成为可能。

好了,下面来看看一个例子:

int k=15,t;
t=k&&k==5&&++k;

运行后得到的 k为什么是 15不是16 ??

====

要理解这个问题分三步:
1.
重点记住
=
的优先级比&&==++都要低,且它的结合性为 右 结合性
&&
的优先级低于==++,且它的结合性为左 结合性
==
的优先级低于++,且它的结合性为 左 结合性
++
的优先级这这个表达式中最高,且它的结合性为 右 结合性

2.时刻想到
逻辑运算符&&||会出现短路现象:
* && *
:当&&的左边为假时短路,此时不再执行&&右边的表达式(注意是&&右边的另一个表达式,而不是右边所有到到语句结束的表达式!!)
* || *
:当||的左边为真时短路,些时不再执行||右边的表达式

3.详细推导
在表达式t=k&&k==5&&++k中,根据运算符的优先级和结合性来确定,表达式相当于:
t= ( k && (k==5) && (++k) )
根据&&的结合性,表达中肯定先验证第一个&&的两边为:k && (k==5)
由于k15,左边为真,并没有短路,所以继续看&&的右边,表达k==5明显为假,值为0,所以表达式k && (k==5)为假,值为0,此时表达简化为:
t= ( 0 && (++k) )
此时表达式中的&&为原表达式中的第二个&&,再看这个表达式的0 && (++k),很明显&&的左边为0,发生短路,那么不再执行&&(++k),所以k保持原值不会为16,此时原表达式又进一步简化为:
t=0
最后,t的值为0k的值不变为15

这样解释,你明白吗?
========

计算机不是人,它不会像人一样直接就找到优先级最高的*号进行运算

理解程序编译过程相当重要

阅读(3167) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~