Register和volatile有什么区别?何时使用哪一个? volatile寄存器变量的含义是什么?

时间:2017-08-08 13:22:49

标签: c volatile storage-class-specifier

Register和volatile之间有什么区别?什么时候使用哪一个? volatile寄存器变量是什么意思?

register int a; volatile int a;

2 个答案:

答案 0 :(得分:4)

volatile表示变量的值可以通过编译器不可见的内容来更改。这意味着变量必须具有有效的内存表示,必须在任何使用之前读取,并在更改时存储。

register - 如果可能,变量应存储在寄存器中。寄存器没有地址,因此不能在它们上使用运算符&。现在大多数编译器都忽略了,除了非常具体的形式:

avr gcc示例:register unsigned char counter asm("r3");

将变量永久绑定到特定寄存器。它减少了寄存器池并使优化更加困难

注册unsigned char counter asm(“r3”);

示例:

volatile int y;

int x8(volatile int x)  // the x is read as many times as it is used
{
    return x * x * x * x * x * x * x * x; 
}

    sub     sp, sp, #8
    str     r0, [sp, #4]
    ldr     r3, [sp, #4]
    ldr     r1, [sp, #4]
    ldr     r2, [sp, #4]
    mul     r3, r1, r3
    mul     r3, r2, r3
    ldr     r2, [sp, #4]
    ldr     r0, [sp, #4]
    mul     r3, r2, r3
    mul     r3, r0, r3
    ldr     r2, [sp, #4]
    ldr     r0, [sp, #4]
    mul     r3, r2, r3
    mul     r3, r0, r3
    ldr     r0, [sp, #4]
    mul     r0, r3, r0
    add     sp, sp, #8
    bx      lr



int test(volatile int x) // parameter changed - stored
{
    return x++;
}

    sub     sp, sp, #8
    str     r0, [sp, #4]
    ldr     r0, [sp, #4]
    add     r3, r0, #1
    str     r3, [sp, #4]
    add     sp, sp, #8
    bx      lr


int test2(void) same as above
{
    return y++;
}
    ldr     r3, .L6
    ldr     r0, [r3]
    add     r2, r0, #1
    str     r2, [r3]
    bx      lr

答案 1 :(得分:4)

当变量的修改可以是异步,例如CPU中的寄存器时,应始终使用

volatile关键字。

示例是您正在使用微控制器,并且按下按钮时您正在等待标记。然后你正在阅读这样的注册:

uint8_t* reg = 0x12345678; //Register address
while (*reg & 0x02) { //Read register until 0 = button pressed

}

这很容易失败,因为编译器会检查一次,之后会忽略值,你可能会以无限循环结束,或者你甚至都得不到任何东西,因为CPU可以缓存reg的值,因为它假定没有人可以修改它指向的价值。

如果你这样做:

volatile uint8_t* reg = 0x12345678; //Register address
while (*reg & 0x02) { //Read register until 0 = button pressed

}

您强制编译器在使用变量内容之前从实际内存中执行读取指令。在这种情况下没有缓存。

register关键字只是编译器的一个提示,它应该将变量放入CPU寄存器,但情况并非总是如此,并且一些编译器会忽略此关键字。它是实现定义。