const 关键字意义,用法与常见问题

来源:互联网 发布:whois域名查询 编辑:程序博客网 时间:2024/05/22 04:58

1.const关键字意义


const是一个C语言的关键字,它限定一个变量不允许被改变。使用const在一定程度上可以提高程序的安全性和可靠性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助。


2.const关键字作用


  (1)可以定义const常量,具有不可变性。 
  例如:const int Max=100; int Array[Max]; 
  (2)便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。
  例如: void f(const int i) { .........} 编译器就会知道i是一个常量,不允许修改; 
  (3)可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。 同宏定义一样,可以做到不变则已,一变都变!
  如(1)中,如果想修改Max的内容,只需要:const int Max=you want;即可! 
  (4)可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。 还是上面的例子,如果在函数体内修改了i,编译器就会报错; 
  例如: void f(const int i) { i=10;//error! } 
  (5) 为函数重载提供了一个参考。 
  class A { ...... 
  void f(int i) {......} //一个函数 
  void f(int i) const {......} //上一个函数的重载 ...... 
  }; 
  (6) 可以节省空间,避免不必要的内存分配。 例如: 
  #define PI 3.14159 //常量宏 
  const doulbe Pi=3.14159; //此时并未将Pi放入RAM中 ...... 
  double i=Pi; //此时为Pi分配内存,以后不再分配! 
  double I=PI; //编译期间进行宏替换,分配内存 
  double j=Pi; //没有内存分配 
  double J=PI; //再进行宏替换,又一次分配内存! 
  const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。 
  (7) 提高了效率。 
  编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。


3.常见失误


(1)const 修饰的是变量,即使是const,但仍然不是常量,所以不可用于数组下标

(2)const于typdef的混合误用

例子:

typedef char * pStr;
char string[4] = "bbc";
const pStr p2 = string; //2式
p2++;
答案与分析:
问题出在p2++上。
1)const使用的基本形式: const type m;
限定m不可变。
3)替换基本形式中的type为2式中的pStr,替换后const pStr m;
限定m不可变,题中的pStr就是一种新类型,因此问题中p2不可变,p2++是错误的。注意,typdef是一个整体的定义,不是像#define这样的简单替换,如果是后者,等同于const char * p2,这样就可以用p2++。

(3)const和指针混用
1)const在前面
const int nValue; //nValue是const
const char *pContent; //*pContent是const, pContent可变(注意,*是一个运算符而不是一个类型变量,所以更靠近“后面”)
const char* const pContent; //pContent和*pContent都是const
2)const在后面,与上面的声明对等
int const nValue; //nValue是const
char const * pContent; //*pContent是const, pContent可变
char* const pContent; //pContent是const,*pContent可变
char const* const pContent; //pContent和*pContent都是const
3)关于const与指针混合使用的类型问题[2]
有这样一个问题,如下代码
foo(const char **p){ }main (int argc, char ** argv){    foo(argv);}

结果编译器发出警告:argument is incompatible with protype
问题:为什么可以用char *s给行参 const char *s赋值,但不能进行上述赋值呢?
查阅资料,得出结论如下如果使得赋值操作合法,需要满足下列条件:
两个操作数都是执行有限定符或者无限定符的相容类型的指针,左边的指针所指向的类型必须具有右边的指针所指向内行的全部限定符号。
所以,在下面的代码中,赋值是合法的:
char *p;
const char *ccp;
ccp=p;
ccp指向的是有const限定符的char的指针;p指向的是没有限定符的char的指针。但是,反过来,p=ccp就是不合法的。注意,const double *类型并不是一个有限定符的指针,const限定符是修饰指针指向的类型而不是指针本身。对指针定义的理解:1)可以把*看作指针类型,*就表示后面定义的变量代表一个指针。2)也可以把它看作是运算符,表示取消指针引用char *p表示,对P取消指针引用后ta是一个char,所以p是指针。
再来看上面的问题,“char **和const char **都是没有限定符的指针类型,但他们指向的类型不同,前者指向char *,后者指向const char *,它们是不相容的。”此时,需要使用指针强制类型转化才可以。但这个解释让人恼火,由此牵扯出相容性不可传递等概念;实际情况下大可不必管他。上面这段解释不能让人信服。
本文来源:谁不小心的csdn博客:const关键字意义,用法与常见问题

外部参考:

[2]:《C专家编程》第一章 1.9小节