或许还有不少人关于const润饰符了解的并不深入,都仅仅停留在一个比较浅的层面上,仅仅是在读他人代码的时分看到了const润饰符的运用,自己的写代码的过中从未运用过,所以天然关于const润饰符比较生疏。那么究竟什么是const润饰符,咱们在自己编写C言语代码的进程中又该怎么有用的运用const润饰符呢,现在让咱们来学习下const润饰符的运用。
const在C言语中算是一个比较新的描述符,咱们称之为常量润饰符,即便是说其所润饰的目标为常量。当你代码中想要设法阻挠一个变量被改动,那么这个时分能够挑选运用const要害字。在你给一个变量加上const润饰符的一同,一般需求对它进行初始化,在之后的程序中就不能再去改动它。
或许有的人会有一个疑问,咱们不是有在C中有预处理指令#define VariableName VariableValue 能够很便利地进行值代替,干嘛还要引进const润饰符呢?!这是由于预处理句子尽管能够很便利的进行值得代替,但它有个比较丧命的缺陷,即预处理句子仅仅仅仅简略值代替,缺少类型的检测机制。这样预处理句子就不能享用C编译器严厉类型查看的优点,正是由于这样,使得它的运用存在着一系列的危险和局限性。
在解说const润饰符之前,咱们在此首要给出const润饰符的几个典型效果:
1. const类型界说:指明变量或目标的值是不能被更新,引进意图是为了替代预编译指令
2. 能够维护被润饰的东西,避免意外的修正,增强程序的健壮性;
3. 编译器一般不为一般const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的功率也很高。
4. 能够节约空间,避免不必要的内存分配。
接下来看看详细的运用。
一、const润饰符在函数体内润饰局部变量。
const int n=5;
和
int const n=5;
是等价的。咱们在编程的进程中必定要清楚的知道const润饰的目标是谁,在这儿润饰的是n,和int没有关系。const 要求他所润饰的目标为常量,不能被改动,一同也不能够被赋值,所以下面这样的写法是过错的。
const int n;
n=0;
关于上面的状况是比较简略了解的,可是当const与指针一同运用时,就简略让人感到利诱。例如,下面咱们来看看一个p和q的声明:
const int *p;
int const *q;
看了上面的代码或许有人会觉得 const int *p;表明的是const int类型的指针(const直接润饰int),而 int const *q;表明的是int类型的const指针(const直接润饰指针)。实际上,在上面的声明中p和q都被声明为const int类型的指针。而int类型的const指针应该这样声明:
int * const r= &n;
以上的p和q都是指向const int类型的指针,也便是说,你在今后的程序里不能改动*p的值。而r是一个const指针,它在声明的时分被初始化指向变量n(即r=&n;)之后,r的值将不再答应被改动,但*r的值能够改动。在此关于判别const的润饰目标给出一种常运用的办法,咱们以*为界限,假如const坐落*的左边,则const便是用来润饰指针所指向的变量,即指针指向为常量;假如const坐落*的右侧,const便是润饰指针自身,即指针自身是常量。
仍是给个代码来加深下咱们的形象吧。
#include
int main(int argc, char* argv[])
{
int ss=9;
int * const r= &ss;
printf("%d\n",*r);
printf("%d\n",ss);
*r=100;
printf("%d\n",*r);
printf("%d\n",ss);
return 0;
}
运转成果如下:
简略的来剖析下吧,由于r指向的是ss的地址,所以修正r指向的地址单元的值的一同ss的值也随之改变。
结合上述两种const润饰的状况,咱们现在应该能够完结怎么声明一个指向const int类型的const指针,如下:
const int * const r=&ss;
这个时分咱们既不能修正*r的值也不能修正r的值。
接下来看看const用于润饰常量静态字符串,例如:例如:
const char* str="fdsafdsa";
假如没有const的润饰,咱们或许会在后边有意无意的写str[4]=’x’这样的句子,这样会导致对只读内存区域的赋值,然后程序会马上反常停止。有了const,这个过错就能在程序被编译的时分就当即查看出来,这便是const的优点。让逻辑过错在编译期被发现。
二、const在函数声明时润饰参数
void *memmove( void* dest, const void* src, size_t count ); 这是规范库中的一个函数,在头文件#include
例如,咱们这儿这样运用它。
#include
#include
int main(int argc, char* argv[])
{
const char* str="hello";
char buf[10];
memmove(buf,str,6);
printf("%s\n",buf);
return 0;
}
运转成果如下:
假如咱们反过来写,memmove(str,buf,6);那么编译器必定会报错。事实是咱们常常会把各种函数的参数次序写反。事实是编译器在此刻帮了咱们大忙。假如编译器静悄悄的不报错,即在函数声明void *memmove( void* dest, const void* src, size_t count ); 处去掉const即可,那么这个程序在运转的时分必定会溃散。这儿还要阐明的一点是在函数参数声明中const一般用来声明指针而不是变量自身。例如,上面的size_t len,在函数完成的时分能够彻底不必更改len的值,那么是否应该把len也声明为常量呢?能够,能够这么做。咱们来剖析这么做有什么好坏。假如加了const,那么关于这个函数的完成者,能够避免他在完成这个函数的时分修正不需求修正的值(len),这样很好。可是关于这个函数的运用者,
1.饰符号毫无意义,咱们能够传递一个常量整数或许一个十分量整数曩昔,横竖对方取得的仅仅咱们传递的一个copy。
2完成。我不需求知道你在完成这个函数的时分是否修正过len的值。
所以,const一般只用来润饰指针。再看一个杂乱的比如
int execv(const char *path, char *const argv[]);
侧重看后边这个,argv.它代表什么。假如去掉const,咱们能够看出char * argv[],argv是一个数组,它的每个元素都是char *类型的指针。假如加上const.那么const润饰的是谁呢?润饰的是一个数组,argv[]意思便是说这个数组的元素是只读的。那么数组的元素的是什么类型呢?是char *类型的指
针.也便是说指针是常量,而它指向的数据不是。所以
argv[1]=NULL; //不合法
argv[0][0]=’a’; //合法
三、const作为大局变量
在程序中,咱们要尽或许少的运用大局变量。由于其效果域是大局,所以程序范围内都能够修正它的值,然后导致了大局变量不能确保值的正确性,假如呈现过错十分难以发现。假如在多线程中运用大局变量,你的程序将会错的乌烟瘴气。多线程会修正另一个线程运用的大局变量的值,假如不注意,一旦犯错后果不堪设想。所以在这种状况下万不满意不要运用大局变量。咱们要尽或许多的运用const。假如一个大局变量只在本文件中运用,那么用法和前面所说的函数局部变量没有什么区别。假如它要在多个文件间同享,那么就牵扯到一个存储类型的问题。
有两种方法。
1.用extern
例如
/* pi.h */
extern const double pi;
/* pi.c */
const double pi=3.14;
然后其他需求运用pi这个变量的,包括pi.h
#include pi.h
或许,自己把那句声明仿制一遍就好。这样做的成果是,整个程序链接完后,一切需求运用pi这个变量的同享一个存储区域。
2.运用static,静态外部存储类
/* constant.h */
static const double pi=3.14;
需求运用这个变量的*.c文件中,有必要包括这个头文件。前面的static必定不能少。不然链接的时分会陈述说该变量被屡次界说。这样做的成果是,每个包括了constant.h的*.c文件,都有一份该变量自己的copy,该变量实际上仍是被界说了屡次,占用了多个存储空间,不过在加了static要害字后,处理了文件间重界说的抵触。害处是浪费了存储空间,导致链接完后的可履行文件变大。一般来说,关于存储空间字节的改变不是太大的状况下,不是问题。优点是,你不必关怀这个变量是在哪个文件中被初始化的。
下面再来看看一段代码:
#include
int main()
{
const int a=12;
const int *p=&a; // 这个是指向常量的指针,指针指向一个常量
p++; //能够指针能够自加、自减
p–; //合法
int const *q=&a; // 这个和上面const int *p=&a;是一个意思
int b=12;
int * const r=&b; //这个便是常量指针(常指针),不能自加、自减,而且要初始化
//r++; //编译犯错
const int * const t=&b; //这个便是指向常量的常指针,而且要初始化,用变量初始化
//t++; //编译犯错
p=&b; //const指针能够指向const和非const目标
q=&b; //合法
return 0;
}
为了便于代码的阅览了解,在此就直接在代码后边加注释,就不在这儿做过多的解说了。
综上所述,const 的优点,是引进了常量的概念,让咱们不要去修正不应修正的内存。直接的效果便是让更多的逻辑过错在编译期被发现。所以咱们要尽或许的多运用const。以上内容不免有错,假如过错,请纠正!如需转载,请注明出处!