分类: 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)
由于k为15,左边为真,并没有短路,所以继续看&&的右边,表达k==5明显为假,值为0,所以表达式k && (k==5)为假,值为0,此时表达简化为:
t= ( 0 && (++k) )
此时表达式中的&&为原表达式中的第二个&&,再看这个表达式的0 && (++k),很明显&&的左边为0,发生短路,那么不再执行&&的(++k),所以k保持原值不会为16,此时原表达式又进一步简化为:
t=0
最后,t的值为0,k的值不变为15
这样解释,你明白吗?
========
计算机不是人,它不会像人一样直接就找到优先级最高的*号进行运算
理解程序编译过程相当重要