voliate类型,机器才读取执行代码读取内存后,将读取的内容存到高速缓冲区里,在硬件里是寄存器,这样在一下次读取的时候就可以直接从高速缓存区里面读取(cache),这也是读取速度加快的原因,但是如果在内存中改变这个变量,而且刚刚读取过这个内容,就不会再访问地址去读取。
例如:
int a=i;//从i的所在地址读取值,并放入高速缓冲区或者寄存器
int b=i;//两次读取之间没有改变i的操作,根据编译器的优化原则,直接从缓冲区里面取值再赋值,而不会再去内存里寻址。
这样在一般的程序里不会出现错误,但是在硬件里的中断函数,引起的值得变化,但编译器觉得两句话之间没有更改操作,而会直接继续从缓冲区里读取,造成错误。
voliate的用处就是声明完这个变量或指针后之后,无论什么时候想取这个变量或者这个指针所指地方的值,都必须按照寻地址的方式去内存里面读取这个值。这样就不存在编译器优化检测不准确地情况,在中断函数已经多线程中尤为常见。
参考https://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777432.html
关于指针直接操作地址问题:
#include<stdio.h>
int main()
{
int *p=0x0123;
*p=5;
printf("%d\n", *p);
}
首先这样写是错误的,因为*p只能被赋值一个地址类型的数,而0x0123在编译器来说这是一个数,而不是一个地址,所以进行更改
#include<stdio.h>
int main()
{
int *p=(int *)0x0123;
*p=5;
printf("%d\n", *p);
}
运行结果:
这样的代码是不能直接在电脑运行的,因为带有操作系统的机器都有保护机制,在系统里面不能直接对内存进行操作,会造成不必要的操作,但是在51或arm里面可以,不在操作系统里的程序可以直接对程序进行操作。
关于不同类型的指针的区别:
不同的指针类型,可操作长度的不同之间的区别。