指针可以变化吗?

vis*_*hal 21 c++ pointers volatile

请考虑以下代码:

int square(volatile int *p)
{
    return *p * *p;
}
Run Code Online (Sandbox Code Playgroud)

现在,volatile关键字指示在存储器中的单元的值可以在方式未知(经由信号中断,硬件寄存器或存储器映射I/O例如修改)被改变以在编译程序或具有其他未知的副作用,即使没有在程序代码修改内容.

那么当我们将指针声明为volatile时会发生什么?

上面提到的代码是否总是有效,或者与此有什么不同:

int square(volatile int *p)
{
    int a = *p;
    int b = *p
    return a*b;
}
Run Code Online (Sandbox Code Playgroud)

我们可以最终乘以不同的数字,因为指针是易变的吗?

或者有更好的方法吗?

Dam*_*mon 11

是的,你当然可以有一个易失性指针.

易失性意味着不会多于并且不会低于对易失性对象(无论何种类型)的每次访问都被视为可见的副作用,因此免于优化(特别是,这意味着访问可能不会重新排序或折叠或完全优化了).这对于读取或写入值,调用成员函数以及当然也用于解除引用也是如此.

请注意,当前一段说"重新排序"时,假定执行一个线程.易失性不能替代原子操作或互斥锁/锁.

用更简单的话来说,volatile通常翻译为"不要优化,就像我说的一样".

指针的上下文中,请参阅Chris Lattner众所周知的"每个程序员需要了解的关于未定义行为的文章 "一文中提供的示例性使用模式(是的,该文章是关于C,而不是C++,但同样适用):

如果您正在使用基于LLVM的编译器,则可以取消引用"volatile"空指针以获得崩溃,如果这是您正在寻找的,因为优化器通常不会触及易失性加载和存储.


edm*_*dmz 11

指针可以volatile吗?

绝对; 任何类型,不包括函数和引用,都可以是volatile合格的.

需要注意的是挥发性指针声明T *volatile,不volatile T*,这不是声明一个指针- -volatile.

易失性指针意味着指针值(即其地址而不是指向的值)可能具有编译器在访问时不可见的副作用; 因此,对于那些访问,可能不会考虑源自"as-if规则"的优化.


int square(volatile int *p) { return *p * *p; }

编译器不能假定读取*p取相同的值,因此不允许在变量中缓存其值.如你所说,结果可能会有所不同,而不是正方形*p.

具体示例:假设您有两个ints 数组

int a1 [] = { 1, 2, 3, 4, 5 };
int a2 [] = { 5453, -231, -454123, 7565, -11111 };
Run Code Online (Sandbox Code Playgroud)

以及指向其中一个的指针

int * /*volatile*/ p = a1;
Run Code Online (Sandbox Code Playgroud)

对尖头元素进行一些操作

for (int i = 0; i < sizeof(a1)/sizeof(a1[0]); ++i) 
       *(p + i) *= 2;
Run Code Online (Sandbox Code Playgroud)

这里p有如果你把它要读取每个迭代volatile,因为,也许,它实际上可能指向a2因外部事件.