如果阅读中发现了错误,请及时告诉我,以免误人子弟。
本文由jordanli22结合网络资源整合修改总结而成(部分原创),欢迎转载。
const是一个C语言的关键字,它限定一个变量不允许被改变。也可以说是只可读不可写的变量。
C中const的用法总结起来主要分为以下两种:
1.在定义变量时使用(由于const常量在定义后不能被修改,所以定义时一定要进行初始化操作)
a) 最简单的用法,说明变量为一个常变量
(在以下例子里,int 和const的先后顺序可以改变的,这无所谓):
const int a=100; //a的值不允许修改了,只能是100了。
int const b=200;//b的值不允许修改了,只能是200了。
本质:const在谁后面谁就不可修改,const在最前面则将其后移一位即可,二者等效
b) 说明指针为指向常数的指针,即指针本身的值是可以改变的:
const int *a=&b;//*a的值不允许改变了,但b的值可以改变,const只限制左值
c) 说明指针本身的值不可改变,但指向的内容可改变:
int * const a = &b;//a的值不允许改变,只能指向b,不能指向其他值了
d) 说明指针为指向常数的常指针,即指针本身与指针指向的内容都不可改变:
const int * const a = &b;//*a和a指向的值都不允许改变了
2、在定义函数时使用:
a) 作为参数使用,说明函数体内是不能修改该参数的:
void func(const int a);//a在函数func内不允许改变了
b) 作为返回值使用,说明函数的返回值是不能被修改的:
const int func();//主要是保证返回值不允许是右值
c) 在函数中使用const,情况与定义变量的情况基本一致:
注意:
1、为什么我下面的例子一样用一个const变量来初始化数组,ANSI C的编译器会报告一个错误呢?
const int n = 5;
int a[n];
答案与分析:
1)、这个问题讨论的是“常量”与“只读变量”的区别。常量肯定是只读的,例如5, “abc”,等,肯定是只读的,因为程序中根本没有地方存放它的值,当然也就不能够去修改它。而“只读变量”则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改。C语言关键字const就是用来限定一个变量不允许被改变的修饰符(Qualifier)。上述代码中变量n被修饰为只读变量,可惜再怎么修饰也不是常量。而ANSI C规定数组定义时维度必须是“常量”,“只读变量”也是不可以的。
2)、注意:在ANSI C中,这种写法是错误的,因为数组的大小应该是个常量,而const int n,n只是一个变量(常量 != 不可变的变量,但在标准C++中,这样定义的是一个常量,这种写法是对的,下面再讨论),实际上,根据编译过程及内存分配来看,这种用法本来就应该是合理的,只是 ANSI C对数组的规定限制了它。
3)、那么,在ANSI C 语言中用什么来定义常量呢?答案是enum类型和#define宏,这两个都可以用来定义常量。
2:const变量 & 字符串常量
请问下面的代码有什么问题?
char *p = "i'm hungry!";
p[0]= 'I';
答案与分析:
上面的代码可能会造成内存的非法写操作。分析如下, “i'm hungry”实质上是字符串常量,而常量往往被编译器放在只读的内存区,不可写。p初始指向这个只读的内存区,而p[0] = 'I'则企图去写这个地方,编译器当然不会答应。
3:const变量 & 字符串常量2
请问char a[3] = "abc" 合法吗?使用它有什么隐患?
答案与分析:
在标准C中这是合法的,但是它的生存环境非常狭小;它定义一个大小为3的数组,初始化为“abc”。注意,它没有通常的字符串终止符'\0',因此这个数组只是看起来像C语言中的字符串,实质上却不是,因此所有对字符串进行处理的函数,比如strcpy、printf等,都不能够被使用在这个假字符串上。
4:
const在C和C++中最大的不同是,在C中,const默认具有外部链接,而C++中则是内部链接。所以当你只在定义const常量的文件中使用该常量时,c++不给你的const常量分配空间,此时const int c = 0;相当于#define c 0;(在C++里面const被转化为常量)而在C中,它会给每个const 常量分配内存空间(在C里面const被定义为只读变量)。
请看下面一个程序:
#include <stdio.h>
int main()
{
const int a = 5;
int b[a];
return 0;
}
在vc6.0中命名为.c文件,编译时,编译器提示错误,int b[a]这行:expected constant expression
命名为.cpp文件,则没问题。
这个问题跟编译器无关,code::blocks之所以编译能通过,其实是因为gcc默认是启用编译器扩展的,把工程的build option中的"In C mode ,supper all ISO C90 programs.........."和"treat as errors the warnings demonded by strict ISO ......"两项选上,去掉所有的gcc扩展,实行严格的C90标准,就不能通过编译了。
这个问题其实跟const是所谓“只读”还是“常量”也无关,const在c/c++语法中的确切意义,依然是一个不能通过被它修饰的标识符直接改变的变量。
问题的真正原因是:在c中,常量表达式必须是编译期常量,a不是编译期常量(是运行期常量),无论c90还是c99都如此,但c++没有了这个规定,对此不作限制。正因为const int i在c中不是常量表达式,因此不能用于定义数组。