volatile与指针

前言

volatile ˈ/välədl/ 在嵌入式工作中经常会使用到,因此掌握volatile的使用非常重要。

意义

该关键字的意义就是表示定义的变量值随时都会改变,必须从变量的地址处读取值,所以只有这个变量在使用过程中可能被改变(比如中断程序),就需要用这个关键字说明。
1)volatile,关键字volatile 确保本条指令不会因C 编译器的优化而被省略,且要求每次直接读值。以下边代码举例:

int *ip =...; //设备地址
*ip = 1; //第一个指令
*ip = 2; //第二个指令
// 以上程序compiler可能做优化而成:
int *ip = ...;
*ip = 2;
// 结果第一个指令丢失。如果用volatile, compiler就不允许做任何的优化,从而保证程序的原意:
volatile int *ip = ...;
*ip = 1;
*ip = 2;

2)共享的内存地址,多个程序都对它操作的时候。你的程序并不知道,这个内存何时被改变了。如果不加这个voliatile修饰,程序是利用catch当中的数据,那个可能是过时的了,加了 voliatile,就在需要用的时候,程序重新去那个地址去提取,保证是最新的

使用场景

1.操作系统下多任务环境下任务之间共享标志。
2. 硬件寄存器。
3. 中断和主循环都会用到的全局变量。举例来讲:

unsigned char cnt;
void TIM1_UP_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
	{
		cnt--;
		TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
	}
}
int main(void)
{
	cnt = 10;
	while (cnt) // 这些在编译器中将会形成一个死循环,而不是预计的等待一段时间。
	{
		....
	}
}

volatile和const

volatile和const一起用,没有冲突,const针对本程序而言,保证该值不变;volatile应付其他情况(如多线程,中断),避免优化后出现错误

volatile和指针

举例来讲:

uchar * volatile reg

行代码里volatile修饰的是reg这个变量。所以这里实际上是定义了一个uchar类型的指针,并且这个指针变量本身是volatile 的。但是指针所指的内容并不是volatile的!在实际使用的时候,编译器对代码中指针变量reg本身的操作不会进行优化,但是对reg所指的内容却会作为non-volatile内容处理。通常这种写法一般用在对共享指针的声明上,即这个指针变量有可能会被中断等函数修改。将其定义为volatile以后,编译器每次取指针变量的值的时候都会从内存中载入,这样即使这个变量已经被别的程序修改了,当前函数用的时候也能得到修改后的值(否则通常只在函数开始取一次放在寄存器里,以后就一直使用寄存器内的副本)。

区别代码:

volatile uchar *reg;

这行代码里volatile修饰的是指针所指的内容。所以这里定义了一个uchar类型的指针,并且这个指针指向的是一个volatile的对象。但是指针变量本身并不是volatile的。如果对指针变量reg本身进行计算或者赋值等操作,是可能会被编译器优化的。但是对reg所指向的内容 reg的引用却禁止编译器优化。因为这个指针所指的是一个volatile的对象,所以编译器必须保证对reg的操作都不被优化。通常在驱动程序的开发中,对硬件寄存器指针的定义,都应该采用这种形式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值