第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的用法
随机推荐
- 在java中,怎样创建编写javascript的环境?
刚开始还没有学到这一块的时候,预习的时候也是在网上搜索这一类的信息时候, 可是都是八竿子碰不到边的!在此也是呕心沥血的为读者献上最好的: 1.首先:点击空白处>右键>project: 2. ...
- 面试中的老大难-mysql事务和锁,一次性讲清楚!
众所周知,事务和锁是mysql中非常重要功能,同时也是面试的重点和难点.本文会详细介绍事务和锁的相关概念及其实现原理,相信大家看完之后,一定会对事务和锁有更加深入的理解. 本文主要内容是根据掘金小册& ...
- Nginx的Gzip功能
什么是HTTP压缩 有时候客户端和服务器之间会传输比较大的报文数据,这时候就占用较大的网络带宽和时长.为了节省带宽,加速报文的响应速速,可以将传输的报文数据先进行压缩,然后再进行传输. HTTP支持多 ...
- 虚拟化技术之kvm管理工具virsh常用基础命令(二)
上一篇博客我们主要聊了下virsh 管理kvm虚拟机的命令相关用法和说明,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13508231.html:今天我们来继 ...
- [Hei-Ocelot-Gateway ].Net Core Api网关Ocelot的开箱即用版本
写在前面 很多neter都有在用Ocelot做Api网关,但是Ocelot又不像kong或者其他网关一样,开箱即用.它需要你单独开一个web项目来部署,这样很多同学都在做重复的事了. 这里[Hei.O ...
- Macbook pro 下修改MySQL数据库密码
步骤: 1. 打开终端 Terminal, 找到Mysql 的安装路径,一般默认安装路径为:/usr/local/mysql-5.7.12-osx10.11-x86_64/bin [注:我安装的Mys ...
- 前端路由、后端路由——想要学好vue-router 或者 node.js 必须得明白的两个概念
前端路由和后端路由的概念讲解 引言 正文 一.路由的概念 二.后端路由 三.前端路由 四.其他知识 结束语 引言 无论你是正在学习vue 还是在学习node, 你一定会碰到前端路由和后端路由这两个概念 ...
- SpringMVC接受表单数据
@ 目录 pojo addProduct.jsp ProductController showProduct.jsp 测试结果 pojo 新建实体类Product package pojo; publ ...
- Ubuntu 磁盘满了处理方法。
Ubuntu 磁盘满了处理方法: 1. 如果是虚拟机安装ubuntu,直接给虚拟机安装ubuntu 系统所在的盘符动态分配一点磁盘容量,就可以了. 2. 如果不是虚拟机安装ubuntu,那么有两个办法 ...
- MySQL数据和索引占用空间查询
MySQL数据和索引占用空间查询 查询所有数据库占用磁盘空间大小的SQL语句 SELECT table_schema, -- 数据库名称 concat( TRUNCATE ( sum( data_le ...