【问题标题】:Why is this initialization accepted by the c++ compiler? static int x = x;为什么 c++ 编译器接受这个初始化?静态整数 x = x;
【发布时间】:2018-04-01 03:46:20
【问题描述】:

我刚刚发现了这个:

static int x = x;

为什么 C++ 编译器会接受这种初始化?

我会称之为编译器异常,但有人可能会对此给出一个很好的解释。

因此,对于具有静态存储的数据,可以自行初始化变量...我已经尝试使用 VS2015 和 VS2017 编译器以及其他一些在线 C++ 编译器。

【问题讨论】:

  • 你甚至可以做static int x = (scanf("%d", &x), x);

标签: c++ static initialization


【解决方案1】:

static 和非static 变量实际上是相同的。

名称在其声明符之后和初始化之前立即可见(如果有的话)。因此在

static int x = x;

名称x 在第一次出现后立即可见,并且可以在初始化程序中引用。因为它是静态的,所以它的初始值是很好定义的(它是0)。

这也是合法的,即使在块范围内:

int x = x;

虽然在这里您可能会收到警告,因为 x 正在使用其自己的不确定值进行初始化(在大多数情况下行为未定义)。

这是一件愚蠢的事情,但 C++ 并没有竭尽全力阻止你做愚蠢的事情。例如,您可能想要声明一个指向自身的指针:

void *p = (void*)&p;

这里的初始化器指的是p 的地址而不是它的值,但是名称p 必须是可见的才能使它工作。添加特殊情况规则被认为不值得。

【讨论】:

  • int x = x; at block 是 C++ 中的 UB:不确定值(无符号字符类型除外)的评估是立即 UB,没有像 C11+DR451 中那样的不确定值的部分传播
  • @M.M 那么unsigned char x = x; 是做什么的,如果它不是未定义的?
  • @DanielH 与unsigned char x; 相同。参见 [basic.scope.pdecl]
  • 确实存在很酷的用例;也就是说,它的实用性甚至超出了给出的小例子。不错的答案!
  • 不需要castvoid*,直接赋值即可。
【解决方案2】:

如果您想禁止 C++ 中的所有愚蠢结构(C 也是如此),您会得到一个很长的列表。

与 C 相比,C++ 在实践中是一种非常不同的语言,但它仍然有其根源。而且,至少在开始时,对与 C 兼容的关注非常强烈。即使在今天,C++ 标准也为此目的包含了 C 头文件。

这么多奇怪的东西都可以追溯到C,而C是一门对编译器要求不高但对程序员要求更高的语言。许多构造会产生未定义的行为不确定的值。这有两个主要原因。首先,它更容易正确编写编译器并且系统要求低。这在 C 的早期很重要。这种语言出现在 1972 年,比 Commodore 发布具有 4kB 内存的家用计算机 VIC-20 早了 8 年。其次,它允许编译器以更少的内存使用生成更快的代码,正如刚才提到的,这在过去非常重要。

因此,即使根本没有任何有效的用例(我不排除即使我看不到它也可能存在的可能性),也没有足够充分的理由对此采取措施.

正如基思在他的回答中提到的,如果变量是静态的,那么它将具有值 0,这意味着该值不是不确定的。 static int x = x; 的结果是完全清楚的,为什么要禁止呢?你会让 C++ 规范变得更大、更难维护,并且可能会破坏一些旧代码,只是为了解决一些不成问题的事情。

当涉及到非静态变量时,这是另一回事,因为值是不确定的。这里有一个更好的理由来禁止这个构造,但另一方面,你已经收到了警告。至少如果您使用的是-Wall,您应该这样做。我还可以补充一点,许多警告是警告而不是错误,只是为了不破坏旧代码。但与其禁止对自身进行初始化,不如完全禁止使用未初始化的变量更有意义。

【讨论】:

    猜你喜欢
    • 2015-05-13
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 2020-01-18
    • 1970-01-01
    • 2014-04-20
    • 2011-05-25
    • 2018-02-19
    相关资源
    最近更新 更多