第9课 - const和volatile分析

1. const只读变量

(1)const修饰的变量是只读的,本质上还是变量,并不是真正意义上的常量         ※ const只是告诉编译器该变量不能出现在赋值符号的左边

(2)const修饰的局部变量在栈上分配空间;const修饰的全局变量在全局数据区分配空间

(3)const只在编译期间有用(检查const修饰的变量有没有出现在赋值符号左边,如果有就会编译报错),在运行期间无用

 #include <stdio.h>

 int main()
{
const int cc = ; int *p = (int*)&cc; // cc = 10; // compile error: assignment of read-only variable ‘cc’ printf("cc = %d\n", cc); // cc = 1 *p = ; printf("cc = %d\n", cc); // cc = 10 return ;
}

2. const全局变量的分歧

(1)在标准C语言编译器中,const修饰的全局变量仍然存储于全局数据区,并没有改变存储方式,通过指针可以隐式的修改全局变量的值。

(2)在现代C语言编译器中,将const 修饰的全局变量分配在只读存储区,改变了存储方式,通过指针隐式修改会导致程序段错误

 #include <stdio.h>

 const int g_ci = ;

 int main()
{
int *p = (int *)&g_ci; // g_ci = 10; // compile error: assignment of read-only variable ‘g_ci’ printf("g_ci = %d\n", g_ci); *p = ; // 通过指针隐式修改 printf("g_ci = %d\n", g_ci); return ;
}

使用gcc编译执行(现代C编译器)    ==>    段错误

使用bcc32编译执行(标准C编译器)  ==>    修改成功

3. const的本质

(1)C 语言中的const 使得变量具有只读属性

(2)现代C编译器中的const将具有全局生命周期的变量(全局变量 +  static修饰的局部变量)存储于只读存储区

          

【static修饰局部变量】

 #include <stdio.h>

 int main()
{
const static int si = ; // const修饰static修饰的局部变量 int *p = (int *)&si; *p = ; // 使用gcc、VS2010编译执行会产生段错误
// 使用bcc32编译执行,可以修改si的值为1 printf("si = %d\n", si); return ;
}

【const的本质分析】

 #include <stdio.h>

 const int g_array[] = {};

 void modify(int* p, int v)
{
*p = v;
} int main()
{
int const i = ; // const放在int前后都可以
const static int j = ;
int const array[] = {}; modify((int*)&i, ); // ok
modify((int*)&j, ); // error,j存储在只读存储区
modify((int*)&array[], ); // ok
modify((int*)&g_array[], ); // error,g_array[5]数组存储在只读存储区 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 ;
}

4. const修饰函数参数和返回值

(1)const 修饰函数参数表示在函数体内不希望改变参数的值

(2)const 修饰函数返回值表示返回值不可改变,多用于返回指针的情形

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

      

【const修饰函数参数与返回值】

 #include <stdio.h>

 const char* f(const int i)
{
// i = 5; // error, i不能作为左值 return "swj striving! 2019-12-23 22:23:57";
} int main()
{
char* pc = f(); // 编译会报warning,函数f的返回值为const char* printf("%s\n", pc); pc[] = '_'; // error,试图修改只读存储区中的字符串 printf("%s\n", pc); return ;
}

5. 深藏不露的volatile

(1)volatile 可理解为 "编译器警告指示字"

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

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

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

 

6. 有趣的问题

 const  volatile int i  =  0;

  ⅰ:变量 i 具有什么样的特性?   i为int型变量,每次都必须到内存取值,且i是只读变量

  ⅱ:编译器如何处理这个变量?  i不能作为左值

第9课 - const 和 volatile分析的更多相关文章

  1. 第9课 const和volatile分析

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

  2. const和volatile分析

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

  3. C语言进阶——const 和 volatile 分析09

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

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

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

  5. C++的类型转换:static_cast、dynamic_cast、reinterpret_cast和const_cast(dynamic_cast还支持交叉转换,const_cast将一个类的const、volatile以及__unaligned属性去掉)

    在C++中,存在类型转换,通常意味着存在缺陷(并非绝对).所以,对于类型转换,有如下几个原则:(1)尽量避免类型转换,包括隐式的类型转换(2)如果需要类型转换,尽量使用显式的类型转换,在编译期间转换( ...

  6. C++ const、volatile、mutable的用法 (转)

      const.volatile.mutable的用法 鸣谢作者: http://blog.csdn.net/wuliming_sc/article/details/3717017 const修饰普通 ...

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

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

  8. const、volatile、mutable的用法

    http://blog.csdn.net/wuliming_sc/article/details/3717017 const.volatile.mutable的用法 const修饰普通变量和指针 co ...

  9. C++ 中 const、volatile、mutable的用法

    @2019-01-14 [小记] C++中const.volatile.mutable的用法

随机推荐

  1. MyKTV系统项目的感想

    不粉身碎骨,何以脱胎换骨! 3月11号,我们迎来S1的尾巴.这期间有温暖,默契,有项目.一切刚刚好.刚刚正式接到KTV这个微微型的项目的时候,还是很害怕的,虽然老师在前两天就已经提到也讲到,KTV系统 ...

  2. PAT 2-08. 用扑克牌计算24点(25):

    题目链接:http://www.patest.cn/contests/ds/2-08 解题思路:思路参考24点游戏技巧http://www.24game.com.cn/articles/points2 ...

  3. centos7上借助于xargs快速查询并卸载rpm软件

    在centos上卸载某些软件的时候,如果查询的软件包比较多,可以考虑使用xargs,边查询边卸载 如:下面在查询mysql包时候,将查询结果通过管道传送给xargs,然后使用rpm -e --node ...

  4. RSA非对称加密(java实例代码)

    使用RSA对WebService传递的信息加密解密的基本思想是:服务器端提供一个WebService方法String getServerPublicKey(),客户端可以以此得到服务器端的公钥,然后使 ...

  5. Debian 镜像使用帮助

    链接: Debian 镜像使用帮助 buster: # 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释 deb https://mirrors.tuna.tsinghua ...

  6. golang mysql demo

    Go操作Mysql数据库 使用Go操作MySQL等数据库,一般有两种方式:一是使用database/sql接口,直接在代码里硬编码sql语句:二是使用gorm,即对象关系映射的方式在代码里抽象的操作数 ...

  7. Advances and Open Problems in Federated Learning

    挖个大坑,等有空了再回来填.心心念念的大综述呀(吐血三升)! 郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! 项目地址:https://github.com/open-intellige ...

  8. SPSSAU新功能上线:高级公式、综合得分一键计算!

    一直关注我们的朋友们一定会发现,近期SPSSAU增添了很多新功能. 我们精挑细选出6个最常使用的功能,介绍给大家,看看这些新功能你有没有解锁成功呢? 01 一键删除无效样本 “无效样本”功能中,添加了 ...

  9. CSS 选择器及优先级

    CSS 选择器及优先级 1.根据权值计算 div .class1 #people的权值等于1+10+100=111 .class2 li #age的权值等于10+1+100=111 2.权值相同,那么 ...

  10. MySQL常用指令,java,php程序员,数据库工程师必备。程序员小冰常用资料整理

    MySQL常用指令,java,php程序员,数据库工程师必备.程序员小冰常用资料整理 MySQL常用指令(备查) 最常用的显示命令: 1.显示数据库列表. show databases; 2.显示库中 ...