天天看点

由const引发的一系列问题

         CONST是一个C语言的关键字,它限定一个变量不允许被改变。

使用CONST在一定程度上还能提高程序的安全性和可靠性。CONST在其他编程语言也有出现,如C++、PHP5、C#.net、HC08 C等。

1.const变量  &  常量

为什么使用一个const变量来定义数组,ANSI C的编译器会报错?

const int n = 5;

int a[n];
           

1)这个问题讨论的是“只读变量”和“常量”的区别。常量,例如:5、“abc”等,肯定是只读的,因为常量是被编译器放在内存中的只读区域,这里的只读区域是内存中真正的只读区域,只读的性质由操作系统赋予,人为修改编译通过,但运行崩溃。

        而只读变量,是在内存中分配一个空间存放它的值,虽然由const修饰,但本质上还是变量,所以存储在堆栈和静态存储区,只不过这个值由编译器限定不允许被修改,意思就是C语言的语法规定不允许这样做,在编译时会报错。所以这个操作并不代表const修饰的内存空间属性变成了只读。因此,上述代码中的n是“只读变量”(不能被改变的变量),而不是“常量”,所以ANSI C的编译器会报错。但在C99中,局部数组是可以用变量作长度的。

2)在C++中,这样的定义是对的,C++的编译器把它当作一个常量来处理。只是ANSI C对数组的规定限制了它(实际上用GCC或VS2005编译以上代码,确实没有错误产生,也没有给出警告)。

这是在C++中的操作:

由const引发的一系列问题

运行结果:

由const引发的一系列问题

看来C++编译器确实是这么处理的。

在C中的操作:

由const引发的一系列问题

显然,在C编译器面前,这种做法是错的。

3)在ANSI C中,用的是enum枚举类型和#define宏进行定义。

2.const怎样限定内容?

以下代码中有一个错误:

typedef char* pstr;
char string[]="bbc";
const char* p1=string;
const pstr p2=string;
p1++;
p2++;
           

问题出在 p2++上。

首先来解释一个问题:

由const引发的一系列问题

该错误的意思是等号左边的值必须为“左值”。

什么是左值,简单地说就是内存中一个真正存在的实体,它的特点:不能是常量和立即数。

上面代码中我想把i从“const int ”型强制转换为“int”型,然后把“*p”赋值给“i”,但是编译系统报错,这就说明C++编译器在定义只读变量时,把只读变量看作是常量(这里是i),下面我做个示范:

由const引发的一系列问题

我把(int)i = *p;注释掉了,并且在下面又加了一句  1=*p;  编译器报错,而且与刚才相同。

如此可以得出一个结论,在C++中,“只读变量”被看作是“常量”,所以当我在对“i”进行赋值时会报错,昨天我想对“i”进行修改,结果“*p”改变了“i”没变,更加说明了C++编译器在编译过程中把“i”当作成常量,并且给变量“*p”分配了一个新的内存空间。

现在回到刚才的问题,p2++的错误。

“const char* p1=string;”这是指向常量的指针变量,也就是说:你可以通过改变内存变量的值来进行更改,但你不能通过指针的方式去更改内存中的值。因此,限定了从“*p1”的角度去更改“string”当中的值,但并不限定其他方式如:

由const引发的一系列问题

运行一下:

由const引发的一系列问题

这样修改是正确的,通过修改变量string[0]来修改内存中的值。

再者,由于C++编译器把常变量看作是常量,于是,“*p1”在被const修饰完后,是常量。

而,"const pstr p2=string;"这句在编译期间,被编译器译作"const char *const p2=string;",为什么呢?我是这么理解的,const先对变量进行修饰,也就是“const pstr p2”,先把“p2”修饰为常变量(常量),再把typedef修饰的类型名带入语句中,也就是“const char* p2”,对“*p2”进行修饰。所以:

由const引发的一系列问题
由const引发的一系列问题

“p2”和“*p2”都不能被更改。

3.const & 指针

const int i;                  //定义i是常变量

const int *p;               //定义*p是常变量

const int *const p;      //定义p和*p都是常变量

----------------------------------------------------------------------------------------------

int const i;                  //同 const int i;

int const *p;               //同 const int *p;

int const *const p;      //同 const int *const p;

----------------------------------------------------------------------------------------------

int *p1,p2;                 //p1是整型指针变量,p2是整型变量

const int *p1,p2; 或

int const *p1,p2;        //p2和*p1是常变量,p1是指针变量

const int *const p1,p2;或

int const *const p1,p2; //p2和*p1是常变量(被前一个const修饰),p1是常指针变量(被后一个const修饰)

------------------------------------------------------------------------------------------------------------------------

const在*的左边,则指针指向的变量的值不可变;在*的右边,则指针的指向不可变。简记为“左定值,右定向”。

补充:

在c中,对于const定义的指针,不赋初值编译不报错,即int* const px;等不会报错。但是,在C++中int* const px;和const int* const px;会报错,const int* px;不报错。必须初始化指针的指向int* const px = &x;const int* const px=&x;

强烈建议在初始化时说明指针的指向,防止出现野指针!