const T vs. T const

来源:百度文库 编辑:神马文学网 时间:2024/03/29 22:42:04
1999年2月《Embedded Systems Programming》上刊登的《const T vs. T const》,作者是Dan Saks。
观点1:
任何一个申明都由两主要部分组成:一个或者几个限定符(declaration specifier)和一序列由逗号隔开的申明变量(declarator)。举个例子:static unsigned long int    *x[N];
其中:static unsigned long int   限定符部分;
*x[N]       申明变量部分;
申明变量部分是要申明的变量的名字,它可能和* , [] , () , &(for C++)结合起来使用。我们知道,*用于申明表示变量是指针类型;[]意味着数组;()有两种用法,第一种是作为函数调用操作符;另外一种是用作分组符。
对于上面的例子,x是指向数组(数组元素类型是static unsigned long int)的指针,还是x是一个数组,数组的元素是static unsigned long int* 类型呢?为此,引入观点2。
观点2:
申明变量中如果有操作符(例如 * [] ),按照表达式运算中的优先级规则进行处理。
我们知道,在表达式运算中,* 的优先级比 [] 低。同样在申明变量的处理也是如此。如此以来,上面的疑问就可以解决了。我们看declarator部分:*x[N];由于[]的优先级比较高,所以x是 一个数组在x是一个指针之前。如此以来,*就用来修饰数组元素了。
对于(),如果用作函数调用,它得优先级和[]一样;如果是用于分组作用,它得优先级最高。
观点3:
对于变量申明限定符部分,可能有类型限定符,还可能有非类型限定符(例如:static , extern , virtual)。类型限定符只直接作用于申明体(申明的变量)的类型;而非类型限定符直接作用于申明体。
继续拿前面的例子,x是一个数组,unsigned long int是类型限定符,表示x这个数组的元素类型;而static是非类型限定符,指示x是静态分配内存。
观点4:
对于观点3,非类型限定符主要是针对static来说的,对于const 和volatile来说,它们是类型限定符。
举个例子:const void *vectortable[N]
如果把const当作非类型限定符的话,按照观点3来分析,vectortable是一个数组,const由于是非类型限定符,所以是修饰 vectortable的,于是vectortable是一个指向数组的常量指针,数组元素的类型是void *。事实上不是这样,const是类型限定符,修饰变量vectortable的类型的,这样vectortable是一个指向数组的指针,数组元素类型 是const void *。
观点5:
限定部分的各个限定词之间的前后顺序没关系。
例如:const   VP   t;   和 VP const T等价
const char   *p 等价于 char const   *p;
说明:大多数资料和程序员都习惯将static非类型限定符放在变量申明的最前面,实际上这仅仅是习惯的问题,并不是语言自身的规定。
观点6:
一种申明风格:对于限定部分里面的各个类型限定词,如果有const ,最好把const 放在右边而不是左边。尽量使用 T const 代替 const T,避免错误。
例如:const   char *p; 我们这样写: char const *p。之所以这样做,是为了可读性。注意这个可读性是针对人的,而不是针对编译器的。前面观点5说了,编译器不区分这个顺序。下面我们看看这样书写风格怎 样达到可读性好的效果。
T const *p : 从右往左读(*作为分隔符,标记指针的):p是指针,指向const T;
等价于:const T *p;
T * const p : 从右往左,常量指针指向T
由上可见方便之处了。我们只要按照从右往左边顺序就可以读出来申明的意义。
除此之外,这样写还不会出错。我们看看下面的一个例子。
typedef int *IP;
int a = 3;
const IP t = &a;
此时t是啥类型呢?
按照以前风格,我们替换IP为 int * 得到:const int * t;如此一来,等价于int const * t;也就是说t是指向常整形指针。实际上是否是这样的呢?
答案是否定的。实际上t是指向整形的常指针。正确的理解是代替IP用如下方式:
const    IP    t
int    *const t;
因此,在申明变量的时候,将const放在限定部分的最右边是一种比较好的做法。例如上面对变量t的申明:IP const t;这样保证程序员不会对t的类型产生误解。
注意:如果你非要使用typedef来实现const int   *t,那么就直接typedef const int *CIP;然后:CIP   t;就可以了。
文章出处:DIY部落(http://www.diybl.com/course/3_program/c++/cppsl/2008227/101903.html)