简体   繁体   English

可以用 static 常量初始化 static 变量吗?

[英]Can a static variable be initialized with a static constant?

In this answer I basically needed static int n = -1;这个答案中,我基本上需要static int n = -1; inside a function.在 function 内。 I wanted to avoid magic numbers all over the place so I used this instead:我想避免到处都是幻数,所以我改用了这个:

double f(int i)
{
    static const int sentinel = -1;
    static int n = sentinel;

    if (n == sentinel)
    // ...
}

It was however pointed to me that this is not conformant to standard because sentinel is not a (compile time) constant.然而有人指出,这不符合标准,因为sentinel不是(编译时)常数。

This makes sense to me since I know constant integers were made usable in compile time expressions (eg size of arrays) in C++.这对我来说很有意义,因为我知道常量整数可用于 C++ 中的编译时表达式(例如数组的大小)。 However gcc, clang and icc >v16 compile this code without any warning.但是 gcc、clang 和 icc >v16 编译此代码时没有任何警告。 Only icc <=v16 and MSVC give this warning/error (see on godbolt ).只有 icc <=v16 和 MSVC 会给出这个警告/错误(参见godbolt )。

What does the C Standard say? C 标准怎么说? Does this change between various versions of the standard (c90, c99, c11)?这会在标准的不同版本(c90、c99、c11)之间发生变化吗? If this is not conformant, can we get a warning on gcc and clang?如果这不符合要求,我们能否在 gcc 和 clang 上收到警告? If it is conformant why do old icc and MSVC give errors?如果它是一致的,为什么旧的 icc 和 MSVC 会出错?

static const int sentinel = -1; static int n = sentinel; is conforming C code.符合 C 代码。 It is not strictly conforming C code.它不严格符合 C 代码。

C 2018 defines a strictly conforming program to be one that “shall use only those features of the language and library specified in this document” (C 2018 4. 5). C 2018 将严格符合的程序定义为“应仅使用本文档中指定的语言和库的那些功能”(C 2018 4. 5)。 Strictly conforming programs are those that only use the core language that is fully defined in the standard.严格符合标准的程序是那些只使用标准中完全定义的核心语言的程序。 It defines a conforming program to be one that is “that is acceptable to a conforming implementation” (4. 7).它将符合标准的程序定义为“符合标准的实现可以接受”(4. 7)。 For hosted implementations, a conforming implementation , is one that accepts any strictly conforming program (4. 6)—that is, any compiler or other implementation that supports the core C language but that may also have extensions.对于托管实现,一致实现是接受任何严格一致的程序 (4. 6) 的实现——即支持核心 C 语言但也可能具有扩展的任何编译器或其他实现。

6.7.9 4 says “All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals.” 6.7.9 4 说“具有 static 或线程存储持续时间的 object 的初始化程序中的所有表达式应为常量表达式或字符串文字。” sentinel is clearly not a string literal. sentinel显然不是字符串文字。 Is it a constant expression?是常量表达式吗? Constant expressions are defined in 6.6.常量表达式在 6.6 中定义。 With one exception, they must have operands that are integer constants (that is, literals such as 37 ), sizeof expressions that yield integer constants, _Alignof expressions, floating-point constants, enumeration constants, character constants, or unary & expressions with certain constraints.除了一个例外,它们的操作数必须是 integer 常量(即诸如37之类的文字)、产生 integer 常量的sizeof表达式、 _Alignof表达式、浮点常量、具有某些约束的枚举常量、字符常量或一元&表达式. sentinel is none of these. sentinel不是这些。

The exception is that paragraph 10 says “An implementation may accept other forms of constant expressions.”例外是第 10 段说“一个实现可以接受其他 forms 的常量表达式。” So, GCC and other compilers are free to accept this code if they wish, and therefore, since it is accepted by a conforming implementation, it is conforming code.因此,如果 GCC 和其他编译器愿意,可以自由地接受此代码,因此,由于它被一致的实现接受,因此它是一致的代码。 However, since it is implementation-defined whether this is accepted or not, it is not strictly conforming code.但是,由于它是否被接受是实现定义的,因此它不是严格符合的代码。

This is substantially similar in prior C standards back to 1990, although there are minor changes, such as that _Alignof was not in early versions of the standard.这与 1990 年以前的 C 标准基本相似,尽管有一些细微的变化,例如_Alignof不在标准的早期版本中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM