C语言学习第10篇---const volatile 关键字剖析

举报
CodeAllen 发表于 2021/10/30 01:05:58 2021/10/30
【摘要】 知识来源主要是陈正冲老师的《C语言深度解剖》及Delphi Tang老师的《C语言剖析》,有兴趣的朋友可以看我置顶文章获取   const 修饰的变量是只读的,本质还是变量 修饰的局部变量在栈上分配空间 修饰的全局变量在全局数据区分配空间 只在编译器有用,在运行期无用   在现代的C语言编译器里面,修...

知识来源主要是陈正冲老师的《C语言深度解剖》及Delphi Tang老师的《C语言剖析》,有兴趣的朋友可以看我置顶文章获取

 

const

修饰的变量是只读的,本质还是变量

修饰的局部变量在栈上分配空间

修饰的全局变量在全局数据区分配空间

只在编译器有用,在运行期无用

 

在现代的C语言编译器里面,修改const全局变量会导致程序崩溃

注意:标准C语言编译器不会将const修饰的全局变量存储于只读存储区中,而是存储与可以修改的全局数据区,其值依然可以改变

 

实验1:const的变量本质


  
  1. #include <stdio.h>
  2. const int g_cc = 2;
  3. int main()
  4. {
  5. const int cc = 1;
  6. int* p = (int*)&cc;
  7. printf("cc = %d\n", cc);
  8. *p = 3;
  9. printf("cc = %d\n", cc);
  10. p = (int*)&g_cc;
  11. printf("g_cc = %d\n", g_cc);
  12. *p = 4;
  13. printf("g_cc = %d\n", g_cc);
  14. return 0;
  15. }

 

const的本质:const不能定义为真正意义上的常量

C语言中的const使得变量具有只读shuxing现代C语言编译器中的const将具有全局声明周期的变量存储于只读存储区

 

实验2:const的本质分析


  
  1. #include <stdio.h>
  2. const int g_array[5] = {0};
  3. void modify(int* p, int v)
  4. {
  5. *p = v;
  6. }
  7. int main()
  8. {
  9. int const i = 0;
  10. const static int j = 0;
  11. int const array[5] = {0};
  12. modify((int*)&i, 1); // ok
  13. modify((int*)&j, 2); // error
  14. modify((int*)&array[0], 3); // ok
  15. modify((int*)&g_array[0], 4); // error
  16. printf("i = %d\n", i);
  17. printf("j = %d\n", j);
  18. printf("array[0] = %d\n", array[0]);
  19. printf("g_array[0] = %d\n", g_array[0]);
  20. return 0;
  21. }

const修饰函数参数和fanhuizhiconst修饰函数表示在函数体内不希望改变参数的值

const修饰函数返回值便是返回值不可改变,多用于返回值指针的情形

注意:C语言中的字符串字面量存储于只读存储区,在程序中需要使用const char*指针

 

实验三:const修饰函数参数与返回值


  
  1. #include <stdio.h>
  2. const char* f(const int i)
  3. {
  4. i = 5;
  5. return "Delphi Tang";
  6. }
  7. int main()
  8. {
  9. char* pc = f(0);
  10. printf("%s\n", pc);
  11. pc[6] = '_';
  12. printf("%s\n", pc);
  13. return 0;
  14. }

 

补充:这些都是工作中遇到的问题,总结了下


  
  1. const 修饰的只读变量
  2. 定义 const 只读变量,具有不可变性。
  3. 例如:
  4. const int Max=100;
  5. intArray[Max];
  6. 注意: const 修饰的只读变量必须在定义的同时初始化,想想为什么?
  7. 因为不初始化就是一个随机值,之后又不能赋值
  8. 留一个问题: case 语句后面是否可以是 const 修饰的只读变量呢?请动手测试一下。
  9. 不能,case后边只能是常量,不能是变量
  10. 节约空间,效率更高
  11. 编译器通常不为普通 const 只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。
  12. 例如:
  13. #define M 3 //宏常量
  14. const int N=5; //此时并未将 N 放入内存中
  15. ......
  16. int i=N; //此时为 N 分配内存,以后不再分配!
  17. int I=M; //预编译期间进行宏替换,分配内存
  18. int j=N; //没有内存分配
  19. int J=M; //再进行宏替换,又一次分配内存!
  20. 1.修饰一般变量,可以在前也可以在后
  21. int const i=2; 或 const int i=2;
  22. 2. 修饰数组
  23. 定义或说明一个只读数组可采用如下格式:
  24. int const a[5]={1, 2, 3, 4, 5};或
  25. const int a[5]={1, 2, 3, 4, 5};
  26. 3修饰指针
  27. const int *p; // p 可变, p 指向的对象不可变
  28. int const *p; // p 可变, p 指向的对象不可变
  29. int *const p; // p 不可变, p 指向的对象可变
  30. const int *const p; //指针 p 和 p 指向的对象都不可变
  31. 在平时的授课中发现学生很难记住这几种情况。这里给出一个记忆和理解的方法:
  32. 先忽略类型名(编译器解析的时候也是忽略类型名),我们看 const 离哪个近。“近水楼
  33. 台先得月”,离谁近就修饰谁。
  34. const int *p; //const 修饰*p,p 是指针, *p 是指针指向的对象,不可变
  35. int const *p; //const 修饰*p,p 是指针, *p 是指针指向的对象,不可变
  36. int *const p; //const 修饰 p, p 不可变, p 指向的对象可变
  37. const int *const p; //前一个 const 修饰*p,后一个 const 修饰 p,指针 p 和 p 指向的对象
  38. 都不可变
  39. 4.修饰函数的参数
  40. const 修饰符也可以修饰函数的参数,当不希望这个参数值被函数体内意外改变时使
  41. 用。例如:
  42. void Fun(const int i);
  43. 告诉编译器 i 在函数体中的不能改变,从而防止了使用者的一些无意的或错误的修改。
  44. 5.修饰函数的返回值
  45. const 修饰符也可以修饰函数的返回值,返回值不可被改变。例如:
  46. const int Fun (void);
  47. 在另一连接文件中引用 const 只读变量:
  48. extern const int i; //正确的声明
  49. extern const int j=10; //错误!只读变量的值不能改变。

 

volatile:

可以理解为编译器警告指示字

告诉编译器必须每次去内存中取变量值

主要修饰可能被多个线程访问的变量

也可以修饰可能被未知因数更改的变量

 

小结:

const使得变量具有只读属性

const不能定义真正意义上的常量

const将具有全局生命周期的变量存储于只读存储区

volatile强制编译器减少优化,必须每次都从内存中取值

 

 

 

 

 

 

文章来源: allen5g.blog.csdn.net,作者:CodeAllen的博客,版权归原作者所有,如需转载,请联系作者。

原文链接:allen5g.blog.csdn.net/article/details/78848690

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。