volatile讲解与宏定义
在嵌入式面试时volatile是必考题!
下面来解释一下volatile关键字的作用:
volatile关键字,是用于表明变量代码无法被优化!
比如:
int a = 0;
a = 1;
a = 2;
a = 3;
经过编译器代码优化后:
int a = 0;
a = 3;
省去重复工作,debug下不会作任何优化,但这样的代码效率一般只用在调试下,release模式下会对齐进行优化,在GCC的编译器下会直接对这段代码优化,GCC下没有debug和release模式!
这样的情况对,应用层来说可以解决重复代码,有效提高编码以及运行效率!
但是对于嵌入式开发就不一样了,每个电平对于不同的情况
GPIO_C |= (1<<5);
sleep(0xFFFFF);
GPIO_C |= (0<<5);
这段代码是让LED灯闪烁,但是倘若编译器为其进行了优化就会变成:
sleep(0xFFFFF);
GPIO_C |= (0<<5);
看不到闪烁的情况了,因为编译器觉得GPIO_C最终的结果会是 |= 0<<5,所以直接索性优化掉上面重复代码!
这样的话GPIO_C端口就接受不到高电平,也就无法驱动LED灯亮起,所以这样做是不对的!
所以我们要用到volatile关键,告诉编译器,无论如何都不要尝试对被volatile关键字声明的变量进行优化!
这样的话编译器就不会对齐变量进行优化!
volatile int a = 0;
即使是宏的情况下,编译器也一样会对其进行优化,所以我们要在宏定义里也加上volatile:
#define volatile *(unsigned int*) 0x410000
这里在说说宏定义:
#define BLOCK_2_GPIOB_CRL volatile *(unsigned int*)BLOCK_2_APB2_GPIO_B+0x0 //BLOCK_2_APB2_GPIO_B = 0X100
在运用时
BLOCK_2_GPIOB_CRL |= 1
编译时会出现错误:表达式必须为左值
其实原因很简单,下面给大家看一下预编译文件:
volatile *(unsigned int*)0x100+0x0 |= 1
后面的0x100+0x0就错了!
编译器看成先对0x100地址取值,然后在加上0x0|=1
这样显然是错误的,0x0是立即数,也称为右值,无法赋值的!
所以我们要加上括号增加运算符优先级
volatile *(unsigned int*)(BLOCK_2_APB2_GPIO_B+0x0)
预编译后:
volatile *(unsigned int*)(0x100+0x0) |= 1
这样编译器就会把0x100+0x0的地址里的值|=1
也就是将0x100这块内存地址的值赋予新的值,新值是0x100里的值|=1
因为上面用了赋值运算符=
volatile讲解与宏定义相关推荐
- 大牛深入浅出讲解C语言#define宏定义应用及使用方法
在C语言中,我们使用#define来定义宏.在C程序编译的预处理阶段,预处理器会把宏定义的符号替换成指定的文本. 不带参数的宏 关于宏最常见的就是用来定义数值常量的名称,即没有参数的宏定义,采用如下形 ...
- 深入浅出讲解C语言#define宏定义应用及使用方法
在C语言中,我们使用#define来定义宏.在C程序编译的预处理阶段,预处理器会把宏定义的符号替换成指定的文本. 不带参数的宏 关于宏最常见的就是用来定义数值常量的名称,即没有参数的宏定义,采用如下形 ...
- 宏定义 指针 c语言,C语言宏定义讲解(C和指针 笔记)
关于C语言宏定义#define 最常用的莫过于通过宏定义定义常数了,例如 #define MAX 1000 通过宏定义程序中需要的常量,方便维护被多次引用的变量,并且宏替换在预处理阶段完成, ...
- C/C++常用宏定义,注意事项,宏中#和##的用法
总结下宏和函数的不同之处,以供大家写代码时使用,这段总结摘自<C和指针>一书. 当然宏定义非常重要的,它可以帮助我们防止出错,提高代码的可移植性和可读性等. 下面列举一些成熟软件中常用得宏 ...
- Linux 内核中的宏定义
Linux 内核中的宏定义 rtoax 日期 内核版本:linux-5.10.13 注释版代码:https://github.com/Rtoax/linux-5.10.13 __attribute__ ...
- C语言~宏操作大全(宏定义、内置宏、__FILE__、__LINE__、##用法)
当然宏定义非常重要的,它可以帮助我们防止出错,提高代码的可移植性和可读性等.下面列举一些成熟软件中常用得宏定义1,防止一个头文件被重复包含 #ifndef COMDEF_H #define COMDE ...
- C语言宏定义使用技巧
写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性等等.下面列举一些成熟软件中常用得宏定义...... 1,防止一个头文件被重复包含 #ifndef COMDEF_H ...
- c语言宏定义_掌握C语言,中文编程不是梦
文/Edward 前面我们在讲节程序编译的时候,编译器做的第一步就是预处理.C语言的预处理,其实是编译器在对整个工程编译之前做的一些文本性质的工作,例如我们经常使用的#include,这就是一个典型的 ...
- linux中offsetof与container_of宏定义
linux内核中offsetof与container_of的宏定义 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->M ...
最新文章
- JBoss5.1.0部署SSH2
- 【软考-软件设计师】解释程序实现高级语言的三种方式
- hdu5468 Puzzled Elena
- 解决VS'scanf':this function or variable may be unsafe.`(VS安全函数问题)
- Spark下的word2vec模型训练
- 坦克大战-C语言-详注版
- 2021高考成绩查询省排名,【重磅整理】2021全国各地高考预测分数线出炉,这样估分可以估算全省排名...
- 小白 C 入门并发疯学习路线(书单)
- 卡巴斯基:揭开“火焰”病毒(Flame)的神秘面纱
- cmd链接php mysql数据库_php连接mysql数据库_cmd连接mysql数据库 - MySQL最新手册教程 - php中文网手册...
- MATLAB中的转置 和 复数的共轭转置
- 计算机考研用python_20年苏州大学计算机考研经验
- EasyClick 易点云测
- centos6 yum安装nginx
- 赋能数字化生命力,让企业未来焕发青春
- 微信公众号基础04_分享和录音功能的实现
- 人生=亲情+爱情+金钱+理想+友情?
- mac下使用diskutil给U盘格式化
- 无法打开模块文件“C:\Users\fkg\AppData\Local\Temp\.NETFramework,Version=v4.5.AssemblyAttributes.vb”系统找不到指定文件
- python实现直方图、条形图、折线图、饼图(参数详情)
热门文章
- windows脚本bat批处理 关闭显示器 关闭显示器脚本bat
- 我国常用的微型计算机是,2013云南省全国计算机等级考试二级笔试试卷VB理论考试试题及答案...
- sql重复数据只保留一条_一条SQL完成跨数据库实例Join查询
- r语言 悲观剪枝_R语言实战(5) ——高级数据管理
- phpcms 指定id范围 调用_Dubbogo 源码笔记(二)客户端调用过程
- 螺旋传动设计系统lisp_[罗升机电]第236期 丝杆升降机系统工程之齿轮传动的设计!...
- json接口文档模板_在.Net Core WebAPI下给Swagger增加导出离线文档功能
- python程序变量名_python 变量名的规范
- mysql 补丁 patch6_系统管理-第6部分――补丁(patch)管理和在线更新
- linux 无线 扫描不到网络,在Ubuntu笔记本上搜不到无线信号的解决办法