const只读变量:

  • const修饰的变量是只读的,本质还是一个变量
  • const修饰的局部变量在栈上分配空间
  • const修饰的全局变量在全局函数区分配资源空间
  • const只在编译器有用,在运行期无用

注意:const修饰的变量不是真的常量,他只是告诉编译器该变量不能出现在赋值符号的左边

const全局变量的分歧:

  • 在现代C语言编译器中,修改const全局变量将导致程序崩溃
  • 标准C语言编译器不会将const修饰的全局变量存贮于只读存贮区中,而是存贮可修改的全局数据区,其值依然可以改变

程序实例1:

 #include <stdio.h>

 const int g_cc = ;

 int main()
{
const int cc = ; int* p = (int*)&cc; printf("cc = %d\n", cc); *p = ; printf("cc = %d\n", cc); p = (int*)&g_cc; printf("g_cc = %d\n", g_cc); *p = ; //error printf("g_cc = %d\n", g_cc); return ;
}

这段代码说明,const修饰的局部变量可以使用指针修改,但是const修饰全局变量不可以通过指针进行修改,第21行代码试图修改const修饰全局变量,由于我使用的codeblocks,是一款现代编译器,所以编译阶段会报错,删掉21行代码程序就可以正常运行

const的本质:

  • C语言的const使得变量具有只读属性
  • 现代C编译器中的const将具有全局生命周期的变量存贮于只读存贮区
  • const不能顶第一真正意义上的常量

程序示例2:

 #include <stdio.h>

 const int g_array[] = {};

 void modify(int* p, int v)
{
*p = v;
} int main()
{
int const i = ;
const static int j = ;
int const array[] = {}; modify((int*)&i, ); // ok
modify((int*)&j, ); // error
modify((int*)&array[], ); // ok
modify((int*)&g_array[], ); // error printf("i = %d\n", i);
printf("j = %d\n", j);
printf("array[0] = %d\n", array[]);
printf("g_array[0] = %d\n", g_array[]); return ;
}

第3行和第13行声明了用const修饰的具有全局生命周期的变量,所以在试图用指针来修改他们的值的时候,编译器会报错

const修饰函数参数和返回值:

  • const修饰函数参数表示在函数体内不希望改变参数的值
  • const修饰函数返回值表示返回值不可改变,多用于返回指针的情形
  • 小贴示:C语言的字符串字面量存贮于只读存贮区中,在程序中需要使用const char* 指针

程序实例3:

 #include <stdio.h>

 const char* f(const int i)
{
i = ; return "Delphi Tang";
} int main()
{
char* pc = f(); printf("%s\n", pc); pc[] = '_'; printf("%s\n", pc); return ;
}

这段代码是错误的,但是我们来剖析一下,首先编译的时候第5行会出错,我们注释掉,接下来再编译,在12行会给出一个警告,我们用一个char *类型来接受了一个字面值常量,因为只是警告,所以我们可以运行一下,最后运行的时候还是出错了,因为第16行尝试修改了一个字面值常量

深藏不露的volatile:

  • volatile 可以理解为  “编译器警告指示”
  • volatile 告诉编译器必须每次去内存中去该变量值
  • volatile 主要修饰可能被多个线程访问的变量
  • volatile 也可以修饰可能被未知因数更改的变量

示例程序4:

int boj = ;   //编译器在编译的时候发现obj

int a=;
int b=; a= obj; //“聪明“的编译器不会到内存中去找obj对应的值,而是直接替换为10 sleep(); //在另一个线程里面可能已经改变了obj的值 b= obj; //这个时候编译器还是自作聪明的用10来代替obj,而不去内存中去找obj对应的值

这段代码只是一个小的片段,但是已经可以帮助我们理解有的时候编译器的自作聪明可能会导致某些bugconst volatile int i = 0;但是如果在定义一个变量的时候我们加上volatile属性,编译器每次就会去内存中去找到变量对应的值。

小结:

  • const 使得变量具有只读属性
  • const 不能定义真正意义上的常量
  • const将具有全局生命周期的变量存贮于只读存贮区
  • volatile 强制编译器减少优化,必须每次从内存中取值

最新文章

  1. MySQL学习笔记之视图
  2. Flume_初识
  3. 反转链表,时间复杂度O(n),空间复杂度O(1)
  4. jS事件之网站常用效果汇总
  5. DIV CSS 网页兼容全搞定 (IE6 IE7 IE8 IE9 火狐 谷歌)
  6. ajax调用aspx.cs中的WebMethod
  7. endnote设置文献第二行悬挂缩进办法
  8. CodeForces 451C Predict Outcome of the Game
  9. java的nio之:java的nio系列教程之SocketChannel
  10. LAMP一键安装包-CentOS 5/6下自动编译安装Apache,MySQL,PHP
  11. jq的bind用法
  12. (1)html开头解说与案例演示
  13. zju 2972 Hurdles of 110m(简单的dp)
  14. 【Hadoop学习】Apache Hadoop ResourceManager HA
  15. [C语言练习]学生学籍管理系统
  16. 教你如何安装配置Windows7系统 IIS IIS7.5本地浏览测试网站 完整版介绍
  17. X86给龙芯笔记本编译本地工具链(未完待续)
  18. 三、Object 对象常用操作方法
  19. ARX工程必须使用release模式编译
  20. Springboot2.x 集成jsp

热门文章

  1. Js仿腾讯微博效果
  2. node安装express时找不到pakage.json文件;判断安装成功?
  3. Android Studio 小技巧(2):AS中Button文字默认大写的问题
  4. TeeChart for .NET常用属性总结
  5. mvc中尽量避免使用HttpContext.Current.Request
  6. 夜色的 cocos2d-x 开发笔记 03
  7. 拼接sql语句时拼接空字符串报sql错误
  8. Spring MVC框架下提交Date数据无法在controller直接接收
  9. 怎样下载YouTube 4K视频
  10. MySQL入门很简单: 5 索引