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 强制编译器减少优化,必须每次从内存中取值

C语言进阶——const 和 volatile 分析09的更多相关文章

  1. 第9课 - const 和 volatile分析

    第9课 - const和volatile分析 1. const只读变量 (1)const修饰的变量是只读的,本质上还是变量,并不是真正意义上的常量         ※※ const只是告诉编译器该变量 ...

  2. 第9课 const和volatile分析

    1. const只读变量——(注意不是真正常量,只是告诉编译器不能出现在赋值号左边!) (1)const修饰的变量是只读的,本质还是变量 (2)const修饰的局部变量在栈上分配空间 (3)const ...

  3. const和volatile分析

    c语言中const修饰的变量是只读的,不能直接作为赋值号的左值,其本质还是变量:会占用内存空间:本质上const在编译器有用,运行时无用(还是可以通过指针改变它的值) ; int *p=&ab ...

  4. C语言进阶——enum, sizeof, typedef 分析11

    枚举类型的使用方法: enum是C语言的 一种自定义类型 enum值是可以根据需要自定义的整型值 第一个enum的值默认为0 默认情况下的enum值是在前一个定义值的基础上加 1 enum类型的变量只 ...

  5. C语言进阶——struct和union分析10

    struct的小秘密: C语言中的struct可以看作变量的集合 struct的问题:空结构体占用多大内存呢? 程序实例1: #include <stdio.h> struct TS { ...

  6. 《C语言进阶剖析》课程目录

    <C语言进阶剖析>学习笔记                                                         本文总结自狄泰软件学院唐佐林老师的<C语言 ...

  7. C语言-const和volatile深度分析

    1.const只读变量 const修饰的变量是只读的.本质还是变量 const修饰的局部变量在栈上分配空间 const修饰的全局变量在全局数据区分配空间 const只在编译期有用,在运行期无用 con ...

  8. C语言中关键字auto、static、register、const、volatile、extern的作用

    原文:C语言中关键字auto.static.register.const.volatile.extern的作用 关键字auto.static.register.const.volatile.exter ...

  9. 【R笔记】R语言进阶之4:数据整形(reshape)

    R语言进阶之4:数据整形(reshape) 2013-05-31 10:15 xxx 网易博客 字号:T | T 从不同途径得到的数据的组织方式是多种多样的,很多数据都要经过整理才能进行有效的分析,数 ...

随机推荐

  1. jquery-fullpage插件

    jquery fullpage.js全屏滚动插件/jquery-easing插件 // 前端自动化工具安装插件 在页面引入: <link rel="stylesheet" h ...

  2. EditText中光标的位置设置

    CharSequence text = userName.getText();              if (text instanceof Spannable) {                ...

  3. python下载文件

    import urllib import urllib2 import requests url = "http://www.blog.pythonlibrary.org/wp-conten ...

  4. C4C和CRM里获取当前登录用户分配的Organization Unit信息

    C4C 如何查看某个用户分配的组织单元ID: 在Employee的Organization Data区域内看到分配的组织名称,如下图红色下划线所示: 现在的需求就是使用ABSL获取当前登录用户分配的O ...

  5. 在TextBox控件中禁用鼠标右键

    实现效果: 知识运用: MouseEventArgs类的Button属性     TextBox控件的ContextMenu属性 实现代码: private void textBox1_MouseDo ...

  6. removing vmware debugger from visual studio

    removing vmware debugger from visual studio by Ross on 十月 14, 2010 at 5:30 下午 under Visual Studio |  ...

  7. app上线

    不管第一次还是第二次APP上线都需要三样东西:开发者证书,appID,描述文件

  8. PASCAL VOC数据集分析

    http://blog.csdn.net/zhangjunbob/article/details/52769381

  9. Vuex基础-Getter

    官方地址:https://vuex.vuejs.org/zh/guide/getters.html Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性).就像 ...

  10. Element表单验证(1)

    Element表单验证(1) 首先要掌握Element官方那几个表单验证的例子,然后才看下面的教程. Element主要使用了async-validator这个库作为表单验证 async-valida ...