Vilatile下内存映射寻址-指针*和取址&的区别

定义:

&是取地址符,他在最前面,输出来的就是地址
*是返回地址所在元素符,他在前面,一般输出的是元素(除非他是指向指针的指针)
然后你问题里的就好回答了
由于&、*是同级运算符,遵循从右往左的运算顺序
*&p是指,先取p的地址,然后回到&p所在的元素
&*p是指,先回到p所在地址的元素,然后取该元素的地址(其实就是p)
例如:
(1)
p=100;
&p=100048;(假设这是p的地址)
*&p=100;(*是取上面那个地址所在的变量)
(2)
p=100048;(此时的p必须是一个地址)
*p=100;(取地址所在变量)
&*p=100048;(&取地址符,又取到了上面那个元素的地址)

二级指针

int **是二级指针 指向的存储单元是个一级指针.是指向指针的指针,

如例子,a是一个存储单元,存储一个地址,这个地址对应的单元也是用来存放地址的。

比如a可以指向一个一维数组,如int **a,b[10][10]; a=&b[1];
这里a指向b数组的第二行数据,用a[i]可以访问b[1][i]。

三 对32位内存映射寄存器进行操

例如:

*(volatile uint32 *)0x60001404 = 0x0000;
意思就是初始化0x60001404地址中的值为0x0000,一般在很多单片机
程序中完成寄存器的操作时经常这样用,它相当于下面两步
   volatile uint32 * p = (volatile uint32 *)0x60001404;
   * p  = 0x0000;
  其中(volatile uint32 *)0x60001404,是利用c语言的强制类型转换把地址值转换为volatile uint32 * 类型的指针(相当于volatile uint32 * p = (volatile uint32 *)0x60001404),然后将0x0000赋给这个指针指向的地址值(相当于 * p  = 0x0000),也就使
0x60001404地址中的值为0x0000。

 例如:

*(volatile uint32 *)0x8a000084 |= (1<<4);  表示把0x8a000084地址中的值与1左移
4位后的值( 即二进制10000)进行算术或操作后的值再赋到0x8a000084地址中

4,Vilatile可见性原理 

  java中volatile关键字,是可以保证共享变量在多线程间具有可见性的。

  完整的说,即一个线程的写操作,对其他线程可见。什么意思呢? 首先理解可见性,反过来问,为什么共享变量在线程间不是可见的呢(严格说是为什么不总是可见呢)?宏观上理解,根据jmm,各个线程对共享变量拥有自己的工作副本,所有的操作,都是针对工作副本操作的,之后刷新副本到主内存,此时,其他线程才可以看到最新的共享变量。如果某一线程更改共享变量后,还未刷新到主存,而另外一个线程对该变量做读取,那么就读不到新值。但实际上,该问题的产生,是编译器对代码进行重排序引起的,例如,当编译器在不影响代码语意情况下,认为写操作放在后面会更有效,就会进行重排序,如果编译器重排某个操作,那么在该写操作完成之前,其他线程就是对该写操作是不可见的,这反应了对缓存的影响。

       深入来说,volatile是通过内存屏障和禁止重排序来保证可见性的:

       1. 对volatile进行写操作时,会在写操作之后增加一个store屏障指令

       2. 对volatile进行读操作时,会在读操作之前增加一个load屏障指令

       简单来说,就是volatile变量进行读时,会有一个主内存到工作内存到拷贝动作,进行写后,会有一个工作内存刷新主内存到动作。

posted @ 2018-11-06 13:34  大海在倾听  阅读(377)  评论(0编辑  收藏  举报