可以使用静态常量初始化静态变量吗?

问题描述 投票:4回答:1

this answer中,我基本上需要在函数内部使用static int n = -1;。我想避免使用幻数,所以我改用它:

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

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

但是有人指出,这不符合标准,因为sentinel不是一个(编译时)常量。

这对我来说很有意义,因为我知道常数整数已在C ++中的编译时表达式(例如数组的大小)中可用。但是,gcc,clang和icc> v16会编译此代码而不会发出任何警告。仅icc <= v16和MSVC给出此警告/错误(请参见godbolt)。

C标准怎么说?在不同版本的标准(c90,c99,c11)之间会发生变化吗?如果这不符合要求,我们可以对gcc和clang发出警告吗?如果一致,为什么旧​​的icc和MSVC会给出错误消息?

c language-lawyer
1个回答
1
投票

static const int sentinel = -1; static int n = sentinel;是合格的C代码。它不是严格符合C代码的语言。

C 2018定义了一个严格符合程序”,它是“仅应使用本文档中指定的语言和库的那些功能”(C 2018 4. 5)。严格一致的程序是仅使用标准中完全定义的核心语言的程序。它将conform program定义为“符合标准的实现可接受的”(4. 7)。对于托管的实现,conforming Implementation是接受任何严格符合程序(4. 6)的程序,即支持核心C语言但也可能具有扩展名的任何编译器或其他实现。

6.7.9 4说:“对于具有静态或线程存储持续时间的对象,初始化程序中的所有表达式都应为常量表达式或字符串文字。” sentinel显然不是字符串文字。它是一个常量表达式吗?常量表达式在6.6中定义。除了一个例外,它们必须具有整数常量(例如37之类的文字),产生整数常量的sizeof表达式,_Alignof表达式,浮点常量,枚举常量,字符常量或具有某些约束的一元&表达式。 sentinel都不是这些。

[例外是第10段说:“实现可以接受其他形式的常量表达式。”因此,GCC和其他编译器可以根据需要自由接受此代码,因此,由于符合标准的实现接受了它,因此它就是符合标准的代码。但是,由于是否接受,这是实现定义的,因此它不是严格符合的代码。

[回溯到1990年,以前的C标准对此基本相似,尽管有一些细微的变化,例如_Alignof不是该标准的早期版本。

© www.soinside.com 2019 - 2024. All rights reserved.