在 C++ 中,您可以在
C
中声明一个类 c.h
,其中包含 static const int var = 3;
的声明和初始化。
class C {
public:
...
static const int var = 3
...
};
除非您使该变量内联,或在您的
c.cpp
,中显式定义它
...
const int C::var;
...
它是未定义的。
var
,例如
for 循环中的计数器未定义行为?我知道必须有某种机制来实现这项工作,因为我见过使用未定义的静态 const 变量的 C++ 代码。但我希望引用该标准。
C 编程语言中会发生这种情况吗?
在 C 中,如果您在头文件中定义变量
static int var = 3;
,则包含此头文件的每个 C 源文件都将拥有自己的本地副本(如果定义了 var
)。不存在声明并初始化但未定义的变量。
请注意,如果配置为生成有用的警告,编译器将报告未使用的
static
变量,因此您应该收到多个警告,除非您在每个源文件中都使用 var
。
Global
const
定义在 C 和 C++ 中的语义略有不同,但这是一个不同的问题。
Per [class.static.data]/4 句子 1 仅当
var
具有 const
限定的整型或枚举类型并且由以下方式初始化时,才允许将静态数据成员的此构造作为一般规则的例外:常量表达式。
每 [class.static.data]/4 句子 2 需要
var
的定义,当且仅当 var
是 odr-used。否则该程序是 IFNDR(格式错误,无需诊断)。
通常,如果变量在潜在求值表达式中命名,则该变量始终是 odr-used。
但是,因为
var
是 const
整型或枚举类型,并使用常量表达式初始化,所以它可以在常量表达式中使用(并且不能有可变子对象),因此 [basic.def 中的异常即使 var
在潜在评估的表达式中被命名,.odr]/4.2也可能适用。如果您在表达式中对
var
所做的只是立即读取其值(左值到右值转换),而不是例如,则此异常本质上适用。形成指向它的指针/引用。因为变量是用常量表达式初始化的,所以编译器可以将变量的使用替换为给var
的编译时常量值。
在 [basic.def.odr]/4.3 中还有另一个小例外,即变量基本上立即被命名为丢弃值表达式,例如当写
var;
作为陈述时。在这种情况下,编译器不需要 var
的值和地址。
这些都与预处理器无关,预处理器甚至在解析实际 C++ 代码之前就专门工作。
我认为这是唯一的例外,您可以对变量进行初始化声明,但同时又不能对其进行定义。它仅因历史原因而存在,因为之前
constexpr
和 inline
可用于变量以使静态数据成员的值可在常量表达式中使用。