第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. 搭建Elasticsearch Logstash Kibana 日志系统

    分布式系统下由于日志文件分布在不同的系统上,分析比较麻烦,通过搭建elk日志系统,可快速排查日志信息. Elasticsearch是大数据处理框架,使用的分布式存储,可存储海量数据:基于Lucense ...

  2. 洛谷P1036.选数(DFS)

    题目描述 已知 n个整数 x1,x2,-,xn,以及11个整数k(k<n).从n个整数中任选k个整数相加,可分别得到一系列的和.例如当n=4,k=3,4个整数分别为3,7,12,19时,可得全部 ...

  3. Dubbo系列之 (二)Registry注册中心-注册(2)

    引导 本章主要介绍下AbstractRegistry.FailbackRegistry的作用和源码. AbstractRegistry 首先,直接引出这个类的作用,该类主要把服务提供者信息缓存本地文件 ...

  4. JDK1.8源码学习-HashMap

    JDK1.8源码学习-HashMap 目录 一.HashMap简介 HashMap 主要用来存放键值对,它是基于哈希表的Map接口实现的,是常用的Java集合之一. 我们都知道在JDK1.8 之前 的 ...

  5. linux,运维,部署 相关

    基础 linux基础命令 linux基础 部署 docker

  6. Build PhantomJS from Source

    Getting the Code To obtain the code using Git from the official repository github.com/ariya/phantomj ...

  7. PHP、JS一些用法

    PHP去除小数点后面的0,保留非零 floatval($num) PHP转数组var d = eval(数组d); PHP字符串转数组 $row['0'] = explode(";" ...

  8. Vue 通过调用百度API获取地理位置-经度纬度省份城市

    一.首先在百度api注册获得ak密钥 二.新建js文件,我命名为loadBMap.js,里面创建script,代码如下: /** * 加载地图 * @param {Function} callback ...

  9. TCP/IP网络编程之数据包协议

    一.概要 在了解了网络字节序之后,接下来就是要讲最最重点的消息协议.数据包是什么呢,数据包可以理解为两个人讲电话说的每一句话的内容.通过大家约定好的方式去理解.达到只有接听电话两个人才懂的东西.在程序 ...

  10. 性能提升40%: 腾讯 TKE 用 eBPF 绕过 conntrack 优化 K8s Service

    Kubernetes Service 用于实现集群中业务之间的互相调用和负载均衡,目前社区的实现主要有userspace,iptables和IPVS三种模式.IPVS模式的性能最好,但依然有优化的空间 ...