分享

const T vs. T const

 昵称502168 2009-12-03
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;就可以了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多