volatile 对象的四个常见示例为:
为内存映射 I/O 端口的对象
多个并行进程之间共享的对象
异步信号处理程序修改的对象
调用 setjmp 的函数中声明的自动存储持续时间对象,其值在 setjmp 调用和相应的 longjmp 调用之间会更改
前三个示例是具有特殊行为的对象的所有实例: 在程序执行期间的任何点均可修改其值。因此,表面上的死循环:
flag = 1; while (flag); |
实际上有效,只要 flag 具有 volatile 限定类型。某些异步事件将来可能将 flag 设置为零。否则,由于 flag 的值在循环主体中保持不变,编译系统会将以上循环更改为完全忽略 flag 值的真正死循环。
第四个示例涉及调用 setjmp 的函数的局部变量,因此进一步加以讨论。关于 setjmp 和 longjmp 行为的细小字体注释表明对于符合第四种情形的对象的值没有任何保证。对于大多数所期望的行为,有必要让 longjmp 检查调用 setjmp 的函数与调用 longjmp 的函数之间的各个栈帧是否有保存的寄存器值。由于存在异步创建栈帧的可能性,使该作业更加困难。
在将自动对象声明为 volatile 限定类型时,编译系统知道生成的代码必须与程序员编写的代码完全匹配。因此,此类自动对象的最新值始终保存在内存中,而不是仅保存在寄存器中,且调用 longjmp 。