在C中,我可以访问自动volatile变量而不必先进行初始化,还是总是导致未定义的行为?
例如,在映射到volatile变量的一些硬件设备中,初始化变量无论如何都没有意义,甚至可能被禁止 .
如果变量是硬件内存映射的I / O位置,则使用volatile而不是atomic,并且显然只应在硬件需要初始化时进行初始化 .
C 11标准规定不应将volatile用于非硬件内存映射I / O.使用原子或其中一种同步类型(事件,互斥,信号量,...)根据需要提供Memory Barrier .
Microsoft和可能的其他一些编译器具有特定于供应商的扩展,它们使用volatile变量提供内存屏障(作为VS2012及更高版本中的命令行选项,始终在旧版本上启用),但这是非标准用法 .
访问未初始化的变量(或内存位置)的值将导致与C标准相关的未定义行为 . 这意味着C标准没有说明会发生什么 .
还有其他来源可以定义在某些情况下会发生什么 . 在volatile变量的情况下,发生的事情的定义几乎总是依赖于平台 .
因此,您需要查阅相关变量的相关文档 .
自动变量通常在call stack上(但这是特定于实现的),因此它通常不会是某些特定于硬件的"device"(除非您的堆栈指针是垃圾) . 在这种情况下(在堆栈上),变量继承自该堆栈位置的先前内容 . 如果它是挥发性的,例如,像
void foo(void) { volatile int x; // here x contains garbage }
访问 x 会给出一些"indeterminate value",并且该访问是未定义的行为 .
x
C标准不需要任何调用堆栈,但大多数C实现使用机器调用堆栈 .
当然,如果你有一个自动变量,它是一个指向一些易失数据的指针,情况会有所不同 .
3 回答
如果变量是硬件内存映射的I / O位置,则使用volatile而不是atomic,并且显然只应在硬件需要初始化时进行初始化 .
C 11标准规定不应将volatile用于非硬件内存映射I / O.使用原子或其中一种同步类型(事件,互斥,信号量,...)根据需要提供Memory Barrier .
Microsoft和可能的其他一些编译器具有特定于供应商的扩展,它们使用volatile变量提供内存屏障(作为VS2012及更高版本中的命令行选项,始终在旧版本上启用),但这是非标准用法 .
访问未初始化的变量(或内存位置)的值将导致与C标准相关的未定义行为 . 这意味着C标准没有说明会发生什么 .
还有其他来源可以定义在某些情况下会发生什么 . 在volatile变量的情况下,发生的事情的定义几乎总是依赖于平台 .
因此,您需要查阅相关变量的相关文档 .
自动变量通常在call stack上(但这是特定于实现的),因此它通常不会是某些特定于硬件的"device"(除非您的堆栈指针是垃圾) . 在这种情况下(在堆栈上),变量继承自该堆栈位置的先前内容 . 如果它是挥发性的,例如,像
访问
x
会给出一些"indeterminate value",并且该访问是未定义的行为 .C标准不需要任何调用堆栈,但大多数C实现使用机器调用堆栈 .
当然,如果你有一个自动变量,它是一个指向一些易失数据的指针,情况会有所不同 .