【问题描述】
看下列4组概念:
(1)
*dates+2 *(dates+2)(2)
*str++; (*str)++; *++str; *(++str);(3)
const int * pt; int * const pt;(4)
int * func(int a, int b); int (* func)(int a, int b);这4组概念怎样区分呢?下面从结合性的角度出发,来分析考虑。
【分析】
(1)
*dates+2 *(dates+2)第一组概念,很多朋友都已经弄清楚了。
从结合性看上述概念,*(间接访问)操作符优先于+(加法)操作符。故*dates+2等价于(*dates)+2。也就是先对指针dates解引用,取出dates的内容。再对dates的内容+2。
而对于*(dates+2),()操作符优先于*和+操作符。故先计算dates+2,即将指针指向dates的第3个内存地址。再对该地址解引用,取出内存的内容。
(2)
*str++; (*str)++; *++str; *(++str);第2组概念,常见与字符串数组中。*str++一般用于将字符串数组指向下一个内存单元,再取出str内容。
从结合性考虑,++操作符的结合性优先于*。有意思的是,++(自增)和*(解引用)操作符的结合性是自右向左的。
*str++等价于*(str++)。也就是先将str进行自增操作,再取出(str++)的内容。
(*str)++,由于()操作符优先于++操作符,故先对str解引用,即取出str的内容,再对str的内容进行自增操作。
*++str和*str++唯一的区别是,自增后,解引用的对象。*++str,解引用的对象是(++str),而*str++解引用的对象是(str++)
*(++str)和*++str是等价的。
关于自增操作符,详见
http://blog.csdn.net/tandesir/article/details/6951349
(3)
const int * pt; int * const pt;第3组概念,如果靠死记硬背的方式理解,很容易就忘记了。
其实从结合性考虑,就很简单了。注意:*的结合性是自右向左的。
这组概念,本身结合性没有什么难点。先看const int * pt,根据结合性,*解引用的对象是pt,说明pt不是const类型,那么const的对象是什么呢?其实,const修饰的是int *pt。即解引用后的对象。说明解引用后的对象不可变。
对于int * const pt,*解引用的对象是const pt。即指针pt是const的,说明指针pt不可变。而解引用后的对象使用int修饰的,并没有声明为const,说明解引用后的对象的内容是可变的。
(4)
int* func(int a, int b); int (* func)(int a, int b);刚学指针时,这组概念感觉很晕乎。下面从结合性来看看。
int * func (int a, int b),func是一个指针函数。()的优先级高于*操作符。故func先与(int a, int b)相结合。很明显,func(int a, int b)是一个函数。func前面加了一个*,难道是对func解引用吗?显然不是,其实int *是一个整体,作为函数func(int a, int b)的返回值。
int (* func )(int a, int b),func是一个函数指针。* func外面加了一个()故func 与*先结合。说明func是一个指针。将(* func)视为一个整体,那么(* func)将与(int a, int b)相结合。说明(* func)是一个函数,该函数的返回值为int类型。那么(* func)又是什么呢?这个大家都明白,就是对指针func解引用,取出func的内容。从全局来看,其实就是定义了一个func指针,该指针解引用(* func)后,指向的内容是一个返回值为int的函数。
【增·2012-1-6】
再看一个实例:
int *f,g;书本中告诉我们,这其实只定义了一个指针(f是指针,而g不是)。这是为什么呢?
从结合性出发,就很好理解。“,”操作符的优先级最低,而*操作符的结合性是自右向左的。故*先与f结合,f是指针。而g并未与*操作符结合,故g不是指针。
定义两个指针,正确的做法是:
int *f,*g;最后,有一点值得注意的是,?:这个唯一的三目操作符结合性是自右向左的,使用时,请注意结合性。
【增·2012-2-12】举个例子吧,如下所示,最大值和最小值通常被定义为:
#define max(x, y) (x)>(y)?(x):(y); #define min(x, y) (x)<(y)?(x):(y);如果x,y的值是普通常量,不会出现什么问题,试想如果x,y是表达式,会怎样呢?
根据结合性,x,y从右向左进行计算。x,y可能被计算两次,这样就可能得不到正确的结果。看看Linux中的处理方案:
Linux-2.6.23/include/linux/kernel.h
/* * min()/max() macros that also do * strict type-checking.. See the * "unnecessary" pointer comparison. */ #define min(x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x < _y ? _x : _y; }) #define max(x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x > _y ? _x : _y; })这样x,y就只计算了一次,避免了可能的错误。
转载于:https://www.cnblogs.com/J2EEPLUS/archive/2012/01/05/2487962.html