静态volatile变量的动态初始化什么时候发生?
When does dynamic initialization of static volatile variable happen?
首先,让我们看一下标准 (C++14 [basic.start.init] 3.6.3/4):
It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable defined in the same translation unit as the variable to be initialized.
volatile
说明符表示可以从外部源修改变量。但是,当无法保证何时初始化时,可能会发生外部修改变量然后动态初始化的情况。或者当有 volatile 关键字时,它的工作方式会有所不同吗?
这是我所说的一个例子:
在 myfile.h
#ifndef MYFILE_H_
#define MYFILE_H_
int my_init ();
#endif /* MYFILE_H_ */
在myfile.cpp
#include <myfile.h>
#include <iostream>
int my_init () {
std::cout << "init" << std::endl;
return 1;
}
static volatile int my_var __attribute__((unused)) = my_init();
在main.cpp
#include <myfile.h>
#include <iostream>
int main() {
std::cout << "main" << std::endl;
// Let's assume first odr-use of my_var or my_init happens down here, maybe
// in a function from another translation unit.
return 0;
}
想象一下 my_init 是一个将 my_var 设置为有效默认状态的函数,以防它不会被外部设置为另一个有效状态。因此,当 my_var 首先从外部修改它,然后再将其设置为默认状态时,就会出现问题。因此,问题是 my_var 何时初始化。正如上面的标准引述所暗示的那样,还是 volatile
改变了游戏规则?
If the initialization is deferred to some point in time after the
first statement of main, it shall occur before the first odr-use (3.2)
of any function or variable defined in the same translation unit as
the variable to be initialized.
你说"can be modified from an external source"。但是任何此类修改都将是对同一翻译单元中定义的变量(实际上是变量)的 ODR 使用。
更重要的是,除非您在某处导出地址或具有修改地址的功能,否则外部资源根本无法访问静态变量。两者都在同一个翻译单元中。同样,初始化发生在使用之前。
我看不到的唯一情况是当您声明变量 volatile 时,因为硬件会在代码的控制之外更改它,例如计时器。但是你最好手动初始化硬件或者知道你的实现是做什么的。初始化的顺序和时间都很重要。
首先,让我们看一下标准 (C++14 [basic.start.init] 3.6.3/4):
It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable defined in the same translation unit as the variable to be initialized.
volatile
说明符表示可以从外部源修改变量。但是,当无法保证何时初始化时,可能会发生外部修改变量然后动态初始化的情况。或者当有 volatile 关键字时,它的工作方式会有所不同吗?
这是我所说的一个例子: 在 myfile.h
#ifndef MYFILE_H_
#define MYFILE_H_
int my_init ();
#endif /* MYFILE_H_ */
在myfile.cpp
#include <myfile.h>
#include <iostream>
int my_init () {
std::cout << "init" << std::endl;
return 1;
}
static volatile int my_var __attribute__((unused)) = my_init();
在main.cpp
#include <myfile.h>
#include <iostream>
int main() {
std::cout << "main" << std::endl;
// Let's assume first odr-use of my_var or my_init happens down here, maybe
// in a function from another translation unit.
return 0;
}
想象一下 my_init 是一个将 my_var 设置为有效默认状态的函数,以防它不会被外部设置为另一个有效状态。因此,当 my_var 首先从外部修改它,然后再将其设置为默认状态时,就会出现问题。因此,问题是 my_var 何时初始化。正如上面的标准引述所暗示的那样,还是 volatile
改变了游戏规则?
If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable defined in the same translation unit as the variable to be initialized.
你说"can be modified from an external source"。但是任何此类修改都将是对同一翻译单元中定义的变量(实际上是变量)的 ODR 使用。
更重要的是,除非您在某处导出地址或具有修改地址的功能,否则外部资源根本无法访问静态变量。两者都在同一个翻译单元中。同样,初始化发生在使用之前。
我看不到的唯一情况是当您声明变量 volatile 时,因为硬件会在代码的控制之外更改它,例如计时器。但是你最好手动初始化硬件或者知道你的实现是做什么的。初始化的顺序和时间都很重要。