欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

对const的总结与思考

程序员文章站 2023-02-20 23:26:46
今天偶然想起const这一关键字,再加之以前几种const修饰指针方式让我印象深刻(混淆不清),重新回顾了一下,自己对这个关键词也又有了更加深刻的理解,所以总结一下。 一、const的定义 const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。 二、const的由来 最初的目的是 ......

  今天偶然想起const这一关键字,再加之以前几种const修饰指针方式让我印象深刻(混淆不清),重新回顾了一下,自己对这个关键词也又有了更加深刻的理解,所以总结一下。

一、const的定义

  const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。

二、const的由来

  最初的目的是为了取代预编译指令define,继承define的优点并且摈弃它的缺点。

举两个例子:

  1.从内存角度

 1 #define   max_d   10
 2 const int max_c = 10;     //此时保存在符号表,未分配内存
 3 
 4 int main(void)
 5 {
 6     int num_d = max_d;   //预编译过后这句话就是int num_d = 10;(分配内存)
 7     int num_c = max_c;   //第一次max_c分配内存
 8             
 9     int num_d1 = max_d;   //预编译替换(分配内存)
10     int num_c1 = max_c;   //之后max_c就不分配内存
11             
12     return 0;
13 }

   2.从语句使用:(const能避免一些宏define因为括号引起的错误)

1 #define   max_d   10 + 20
2 const int max_c = 10 + 20;
3 .....
4 int num_d = max_d / 2; //因为宏的特性预编译后num_d = 10 + 20 / 2
5 int num_c = max_c / 2; //执行后num_c = 30 / 2;

   3.小结

  • 数据类型:cosnt修饰的变量有明确的类型,而宏没有明确的数据类型(不安全,但很灵活->很强大)
  • 安全方面:const修饰的变量会被编译器检查,而宏没有安全检查,可能会发生意外的错误(边界效应)
  • 内存分配:cosnt修饰的变量只会在第一次赋值时分配内存,节省空间,避免不必要的内存分配,同时提高效率,而宏是直接替换,每次替换后的变量都会分配内存 
  • 作用场所:const修饰的变量作用是在编译、运行过程中,而宏作用在预编译
  • 代码调试:cosnt方便调试,宏在预编译进行所以没法调试。

 三、const的使用

  1.修饰只读常量,不能被改变。改变报错。

  2.修饰一般变量(const的位置可以在类型说明符前或后)

1 int const num=2; 
2 const int num=2;

  3.修饰只读数组(const的位置可以在类型说明符前或后)

1 int const num[2]={1, 2};  
2 const int num[2]={1, 2};

  4.修饰指针(四种形式)

1 const int *ptr;               //ptr可变,指向对象不能变
2 int const *ptr;               //ptr可变,指向对象不能变
3 int * const ptr;              //ptr不可变,指向对象可变
4 const int * const ptr;        //ptr都不可变

  我也搞混淆了很多次,不过总结了一下,在分析就完全ok了。

  ①首先我们得知道const一次只能修饰一个变量

  ②然后我们得根据就近原则,所谓“近水楼台先得月”来判断哪个变量跟cosnt最近,是(*ptr)还是ptr。

  ③之前也有提到const的位置可以在类型说明符前或后。

1 const int *ptr;               //const与*ptr近,与ptr远
2 int const *ptr;               //const与*ptr近,与ptr远
3 int * const ptr;              //const与ptr近,已经拆分了*ptr
4 const int * const ptr;        //第二个const与ptr近,第一个const显然与(* const ptr)近

   5.修饰函数参数

1 void fun(const int *p);       //意义指针变量本身可变,p所指向的变量不可变

  ①告诉编译器传入参数不能改变,防止使用者的无意或错误的修改

  ②修饰指针传参,就是在声明函数内部不会改变这个指针所指向的内容。(一般是做函数输入参数)

  ③补充:这也可以只知道函数原型时可以大概去判断函数列表里的输入参数与输出参数

  6.修饰返回值

const int fun (void);   //返回值不可被改变。

四、补充

  1.const常量可以被改变(gcc环境下)

1 const int num = 5;
2 int *p = (int *)#            //强制类型转换来消除警告;
3 *p = 10;
4 printf("num = %d.\n", num);      //num = 10,const类型的变量被修改

  原因:

  ①const在c的规定中并未有明确规定,const修饰的变量存放在哪里

  ②在gcc环境下,const是通过编译器在编译的时候执行安全检查,在程序运行过程中并不会报错。

  ③内存的储存上,gcc把const类型的常量也放在了data段

  ④所以根据这些特性,通过强大的指针骗过编译器就可以改变了

五、总结

  1.const的合理使用能告诉编译器哪些变量不希望改变,防止无意的被修改,减少bug,也使代码更严谨。

  2.const的使用也是为读代码的人传递很有用的信息,间接或直接告诉使用者这个变量不应该被修改。

 


 

 作者:devil-wei

出处:https://www.cnblogs.com/devil-wei/

版权声明:本文版权归作者和博客园共有,转载请标注文章作者与出处