第9课 - const 和 volatile分析
第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分析的更多相关文章
- 第9课 const和volatile分析
1. const只读变量——(注意不是真正常量,只是告诉编译器不能出现在赋值号左边!) (1)const修饰的变量是只读的,本质还是变量 (2)const修饰的局部变量在栈上分配空间 (3)const ...
- const和volatile分析
c语言中const修饰的变量是只读的,不能直接作为赋值号的左值,其本质还是变量:会占用内存空间:本质上const在编译器有用,运行时无用(还是可以通过指针改变它的值) ; int *p=&ab ...
- C语言进阶——const 和 volatile 分析09
const只读变量: const修饰的变量是只读的,本质还是一个变量 const修饰的局部变量在栈上分配空间 const修饰的全局变量在全局函数区分配资源空间 const只在编译器有用,在运行期无用 ...
- C语言-const和volatile深度分析
1.const只读变量 const修饰的变量是只读的.本质还是变量 const修饰的局部变量在栈上分配空间 const修饰的全局变量在全局数据区分配空间 const只在编译期有用,在运行期无用 con ...
- C++的类型转换:static_cast、dynamic_cast、reinterpret_cast和const_cast(dynamic_cast还支持交叉转换,const_cast将一个类的const、volatile以及__unaligned属性去掉)
在C++中,存在类型转换,通常意味着存在缺陷(并非绝对).所以,对于类型转换,有如下几个原则:(1)尽量避免类型转换,包括隐式的类型转换(2)如果需要类型转换,尽量使用显式的类型转换,在编译期间转换( ...
- C++ const、volatile、mutable的用法 (转)
const.volatile.mutable的用法 鸣谢作者: http://blog.csdn.net/wuliming_sc/article/details/3717017 const修饰普通 ...
- C语言中关键字auto、static、register、const、volatile、extern的作用
原文:C语言中关键字auto.static.register.const.volatile.extern的作用 关键字auto.static.register.const.volatile.exter ...
- const、volatile、mutable的用法
http://blog.csdn.net/wuliming_sc/article/details/3717017 const.volatile.mutable的用法 const修饰普通变量和指针 co ...
- C++ 中 const、volatile、mutable的用法
@2019-01-14 [小记] C++中const.volatile.mutable的用法
随机推荐
- 搭建Elasticsearch Logstash Kibana 日志系统
分布式系统下由于日志文件分布在不同的系统上,分析比较麻烦,通过搭建elk日志系统,可快速排查日志信息. Elasticsearch是大数据处理框架,使用的分布式存储,可存储海量数据:基于Lucense ...
- 洛谷P1036.选数(DFS)
题目描述 已知 n个整数 x1,x2,-,xn,以及11个整数k(k<n).从n个整数中任选k个整数相加,可分别得到一系列的和.例如当n=4,k=3,4个整数分别为3,7,12,19时,可得全部 ...
- Dubbo系列之 (二)Registry注册中心-注册(2)
引导 本章主要介绍下AbstractRegistry.FailbackRegistry的作用和源码. AbstractRegistry 首先,直接引出这个类的作用,该类主要把服务提供者信息缓存本地文件 ...
- JDK1.8源码学习-HashMap
JDK1.8源码学习-HashMap 目录 一.HashMap简介 HashMap 主要用来存放键值对,它是基于哈希表的Map接口实现的,是常用的Java集合之一. 我们都知道在JDK1.8 之前 的 ...
- linux,运维,部署 相关
基础 linux基础命令 linux基础 部署 docker
- Build PhantomJS from Source
Getting the Code To obtain the code using Git from the official repository github.com/ariya/phantomj ...
- PHP、JS一些用法
PHP去除小数点后面的0,保留非零 floatval($num) PHP转数组var d = eval(数组d); PHP字符串转数组 $row['0'] = explode(";" ...
- Vue 通过调用百度API获取地理位置-经度纬度省份城市
一.首先在百度api注册获得ak密钥 二.新建js文件,我命名为loadBMap.js,里面创建script,代码如下: /** * 加载地图 * @param {Function} callback ...
- TCP/IP网络编程之数据包协议
一.概要 在了解了网络字节序之后,接下来就是要讲最最重点的消息协议.数据包是什么呢,数据包可以理解为两个人讲电话说的每一句话的内容.通过大家约定好的方式去理解.达到只有接听电话两个人才懂的东西.在程序 ...
- 性能提升40%: 腾讯 TKE 用 eBPF 绕过 conntrack 优化 K8s Service
Kubernetes Service 用于实现集群中业务之间的互相调用和负载均衡,目前社区的实现主要有userspace,iptables和IPVS三种模式.IPVS模式的性能最好,但依然有优化的空间 ...
