C语言的const关键字

  • C语言的const关键字与指针搭配使用


  • C语言的const关键字与指针搭配使用,const是C语言中保留的一个关键字,它用来限定一个变量是只读的,即不可变的。程序中使用const可以在一定程度上提高程序的健壮性,但是程序中使用过多的const,可能在对代码的阅读时增加一定的难度。
  • C语言的const关键字与指针搭配使用,const是C语言中保留的一个关键字,它用来限定一个变量是只读的,即不可变的。程序中使用const可以在一定程度上提高程序的健壮性,但是程序中使用过多的const,可能在对代码的阅读时增加一定的难度。

    (1)用const修饰一般变量

    注意在C语言中,用const修饰的变量必须在声明时进行初始化(用来修饰函数的形参除外);

    如:

       
       
    1. const int n; 这种声明方式是错误的  
    2. const int n=5; 正确  
    3. void fun(const int n); 正确  
    4. const char a; 错误  
    5. char * const p; 错误  
    6. const char *p;正确(注意这种为什么是正确的),因为这里const是修饰p指向的变量,而不是指针变量p本身 

    一旦一个变量被const修饰后,在程序中除初始化外对这个变量进行的赋值都是错误的。

    如:

       
       
    1. const int n=5;  
    2. n=3; 错误 

    (2)const与指针搭配使用

    首先必须弄清楚两个基础概念:指针常量和常量指针

    指针常量:即指针本身的值是不可改变的,而指针指向的变量的值是可以改变的;

    常量指针:即指针指向的变量的值是不可改变的,而指针本身的值是可以改变的;

    可以这样去理解:因为指针本身也是一个变量,只不过指针存放的是地址而已,而一旦指针变成了常量,即指针本身的值是不可变的,此时指针只能指向固定的存储单元;指针一般会指向一个变量,如果该变量成为一个常量,那么该变量的值就不能被修改,即常量指针,指针指向的是一个不可变的变量。

    如:

       
       
    1. int a=3;  
    2. const int *p=&a;  
    3. int const *p1=&a;  
    4. *p=4;  
    5. a=4;  

    第2行和第3行是等价的;

    第四行是错误的,因为用const限定p指向的变量的值是不可修改的,即不可通过指针p去修改变量a的值;

    第五行是正确的,因为a本身没用const进行修饰,即a本身的值是可以修改的.

       
       
    1. int a=1;   
    2. int b=2;   
    3. const int *p;   
    4. int const *p1;   
    5. int * const p2;   
    6. int * const p3=&b   
    7. p=&a;   
    8. p1=&a;   
    9. p2=&b;  
    10. p3=&a; 

    第3、4、7、8行是正确的;

    第5行是错误的,第6行是正确的,第10行是错误的,因为const在'*'后面,表示是来修饰指针变量本身,因此在声明时必须进行初始化,并且在后面不能再指向其它的变量.

       
       
    1. #include<stdio.h>  
    2. int main(void)  
    3. const int a=3;   
    4. int *pa=&a;   
    5. *pa=4;   
    6. printf("%d ",*pa);   
    7. printf("%d ",a);   
    8. return 0;  
    9. }  
    10.  

    编译结果:e:\c++\test\test.c(6) : warning C4090: 'initializing' : different 'const' qualifiers输出结果是: 4

    从这里可以看出a的值被修改了,在C语言中用const去修饰整形变量a,即a的值是不可变的,不能显示地通过赋值语句去改变a的值,

    但是不代表在程序中不能通过其它方法来修改这个值。

    总结:(1)在C语言中用const去修饰一个变量,表示这个变量是只读的,不可通过显式的调用a去修改a的值,并且此时a仍然是一个变 量,不能等同于常量;

    (2)要注意const在声明变量时所处的位置,位置不同,在意义上可能会有很大的不同。

    如果const在'*'左边,则表示指针指向的变量的值不可变;

    如果const在'*'右边,则表示指针的值是不可变的;



C语言中的const一直是C语言初学者心中的痛,这是因为const在不同位置有不同作用,在不同情景有不同角色。这让初学者摸不清头脑。今天,和大家一起研究一下const,让它的每个角色都“深入人心”!

==============================================================================================

情景一:最简单的const用法

#include<stdio.h>
int main()
{
int const a;
a=5;
printf("a=%d\n",a);
return 0;
}

如果编译这个c文件,就会报错:

1071.c: In function ‘main’:
1071.c:5: error: assignment of read-only variable ‘a’

显而易见,这是const在搞鬼,因为声明了const的变量是不能修改的!

如果将源代码修改为如下这样,就没有问题了!

#include<stdio.h>
int main()
{
int const a=5;
printf("a=%d\n",a);
return 0;
}

总结:const声明的变量必须要进行初始化赋值,如果错过这个机会,以后再想给const的变量赋值,可就没门了!切记~

PS:int const和const int是一回事,“颠倒写”都是可以的。以后遇到了别犯晕,呵呵。但是,还是要留个心眼,当const和指针搀和到一起时,这个“颠倒写”的规律可未必成立。

==============================================================================================

情景二:发明const为了什么?

在const诞生之前,开发者一直使用#define VAR 100来定义一些有特殊用途的类常量,不过这样定义是存在一些劣势的。因此const应运而生,之后开发者可以使用const int VAR=100;来定义类常量了。

至于为什么#define有其劣势,还要读者自己去google下。:)

==============================================================================================

情景三:const和指针的配合是噩梦!

你能分辨得清这些声明么:

const int *A;
int const *A;
int *const A;
const int *const A;

如果有点犯晕的话,那就先给出它们的讲解,然后继续看后面的情景分析吧。

const int *A; //修饰指向的对象,A可变,A指向的对象不可变
int const *A;   //修饰指向的对象,A可变,A指向的对象不可变
int *const A;   //修饰指针A, A不可变,A指向的对象可变
const int *const A; //指针A和A指向的对象都不可变

==============================================================================================

情景四:const int *A

[rocrocket@wupengchong const_test]$ cat test1.c

#include<stdio.h>
int main()
{
int num=12;
const int *A=&num;
printf("result=%d\n",*A);
return 0;
}

编译执行结果为:

[rocrocket@wupengchong const_test]$ cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=12

接下来,我们动动手脚,在代码中加入了(*A)++;这条语句:

[rocrocket@wupengchong const_test]$ cat test1.c

#include<stdio.h>
int main()
{
int num=12;
const int *A=&num;
(*A)++;
printf("result=%d\n",*A);
return 0;
}

编译这个c文件:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function ‘main’:
test1.c:6: error: increment of read-only location ‘*A’
可以看到,报错了,报错的内容表示”*A”是只读的,不能修改。

我们再修改一下源代码为下面这样:

[rocrocket@wupengchong const_test]$ cat test1.c

#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
const int *A=&num;
A=&tmp;
printf("result=%d\n",*A);
return 0;
}

编译执行结果为:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=100

好了,如果你仔细看了这几个小得不能再小的程序,你自己都可以给出结论了!

结论:如果声明了const int *A,那么A值是可以修改的,而*A是不可以修改的。更通俗的说,A指针可以随便指向一个整型,但只要被A盯上了的整型变量在使用*A引用时就不能修改了。

[rocrocket@wupengchong const_test]$ cat test1.c

#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
const int *A=&num;
A=&tmp;
tmp=3;
printf("result=%d\n",*A);
return 0;
}

编译执行的结果为:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=3

结论2:即使A指向了tmp,我虽然不能修改*A,但是我仍然是可以用tmp来修改这个值的,完全不管*A的存在。呵呵

==============================================================================================

情景五:int *const A

[rocrocket@wupengchong const_test]$ cat test1.c

#include<stdio.h>
int main()
{
int num=12;
int *const A=&num;
printf("result=%d\n",*A);
return 0;
}

编译执行结果为:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=12

我们稍微修改下源代码:

[rocrocket@wupengchong const_test]$ cat test1.c

#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
int *const A=&num;
A=&tmp;
printf("result=%d\n",*A);
return 0;
}

编译时报错了:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function ‘main’:
test1.c:7: error: assignment of read-only variable ‘A’
[rocrocket@wupengchong const_test]$ cat test1.c

可见A本身的值已经不能再变了。

继续修改源代码如下:

[rocrocket@wupengchong const_test]$ cat test1.c

#include<stdio.h>
int main()
{
int num=12;
int *const A=&num;
(*A)=100;
printf("result=%d\n",*A);
return 0;
}

编译执行结果为:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=100

可以看出,(*A)是可以改变的。

结论又可以轻易推出了:int *const A;   //const修饰指针A, A不可变,A指向的对象可变

==============================================================================================

情景六:const int *const A; //指针A和A指向的对象都不可变

[rocrocket@wupengchong const_test]$ cat test1.c

#include<stdio.h>
int main()
{
int num=12;
int const *const A=&num;
(*A)=100;
printf("result=%d\n",*A);
return 0;
}

编译会报错:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function ‘main’:
test1.c:6: error: assignment of read-only location ‘*A’

改下源代码:

[rocrocket@wupengchong const_test]$ cat test1.c

#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
int const *const A=&num;
A=&tmp;
printf("result=%d\n",*A);
return 0;
}

编译仍然会报错:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function ‘main’:
test1.c:7: error: assignment of read-only variable ‘A’

呵呵,结论很明显了,const int *const A; //指针A和A指向的对象都不可变

当然const int *const A;和int const *const A=&num;是等价的!

情景七:如果const用在函数形参里呢?是不是又要复杂很多?

答案是NO!一点也不复杂。

来看看这个函数投:int addnum(const int num, int a, int b);

这个函数声明中的第一个形参是const int num,这就表明如果我调用了这个函数,那么第一个实参被传到addnum函数里之后,就不能再做修改了!呵呵 就这么简单。

给个例子吧,让大家能更一目了然:

[rocrocket@wupengchong const_test]$ cat test2.c

#include<stdio.h>
int addto(const int num, int a, int b)
{
if(num==1){
return a+b;
}else{
return 0;
}
}
 
int main(){
int num=100;
int a=12,b=22;
int res;
num=1;
res=addto(num,a,b);
printf("res=%d\n",res);
return 0;
}

编译执行结果为:

[rocrocket@wupengchong const_test]$ !cc
cc test2.c
[rocrocket@wupengchong const_test]$ ./a.out
res=34

如果我修改一下,编译就会出错:

[rocrocket@wupengchong const_test]$ cat test2.c

#include<stdio.h>
int addto(const int num, int a, int b)
{
if(num==1){
num=3;
return a+b;
}else{
return 0;
}
}
 
int main(){
int num=100;
int a=12,b=22;
int res;
num=1;
res=addto(num,a,b);
printf("res=%d\n",res);
return 0;
}

编译报错为:

[rocrocket@wupengchong const_test]$ !cc
cc test2.c
test2.c: In function ‘addto’:
test2.c:5: error: assignment of read-only location ‘num’

可见在函数里形参被声明为const的变量也是不能修改的哦!呵呵~

const其实不难,把本文的几个小例子看懂就OK了!

================================================================================

最后附上在北邮人论坛上看到ebirthatsix对const的评论:

除了传递要求为const的参数以外,自己声明对象没有什么必须要加,但是对于一个逻辑上不应该被修改,应该为常量的对象,没有声明为const,就必须由程序员自己来维护,来记住这个变量不应该被修改,即使你不小心修改导致程序整体混乱了,编译器也不会报错
另,const和普通变量的声明存在于头文件时有区别,总之这些都是与你具体写程序的规划有关系,const这个玩意只是方便程序设计和程序编写,能够使程序更加的清晰,如果说我就是不爱用,就是喜欢一路变量用到底,那也没什么不行。。。

OK,over~

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值