gpt4 book ai didi

c++ - 为什么 0 == ("abcde"+1) 不是常量表达式?

转载 作者:IT老高 更新时间:2023-10-28 21:52:57 25 4
gpt4 key购买 nike

为什么下面的代码不能编译?

// source.cpp

int main()
{
constexpr bool result = (0 == ("abcde"+1));
}

编译命令:

$ g++ -std=c++14 -c source.cpp

输出:

source.cpp: In function ‘int main()’:
source.cpp:4:32: error: ‘((((const char*)"abcde") + 1u) == 0u)’ is not a constant expression
constexpr bool result = (0 == ("abcde"+1));
~~~^~~~~~~~~~~~~~~

我正在使用 gcc6.4。

最佳答案

对可以在常量表达式中使用的内容的限制主要定义为否定列表。有一堆你不能评估的东西([expr.const]/2 在 C++14 中)和某些值必须导致的东西([expr.const]/4 在 C++14 中)。此列表随标准而变化,随着时间的推移变得更加宽松。

在尝试评估时:

constexpr bool result = (0 == ("abcde"+1));

没有不允许我们评估的内容,也没有不允许我们获得的任何结果。没有未定义的行为等。这是一个完全有效的表达,如果奇怪的话。只有一个 gcc 6.3 碰巧不允许 - 这是一个编译器错误。 gcc 7+、clang 3.5+、msvc 都可以编译。


关于这个问题似乎有很多混淆,许多评论表明,由于像 "abcde" 这样的字符串文字的值直到运行时才知道,所以你不能对这样的东西做任何事情持续评估期间的指针。重要的是要解释为什么这是不正确的。

让我们从如下声明开始:

constexpr char const* p = "abcde";

这个指针有一些值。假设 N。关键是 - 你可以做的任何事情来尝试观察 N 在持续评估期间 将是不正确的。你不能cast it to an integer读取值。您无法将其与 a different, unrelated string 进行比较(通过 [expr.rel]/4.3 ):

constexpr char const* q = "hello";
p > q; // ill-formed
p <= q; // ill-formed
p != q; // ok, false

我们可以肯定地说 p != q 因为它们指向哪里,它们显然是不同的。但我们不能说哪个先走。这样的比较是未定义的行为,未定义的行为 is disallowed在常量表达式中。

你真的可以比较同一个数组中的指针:

constexpr char const* a = p + 1; // ok
constexpr char const* b = p + 17; // ill-formed
a > p; // ok, true

无论p 指向哪里,我们知道 a 指向它之后。但是我们不需要知道 N 来确定这一点。

因此,在常量求值期间的实际值 N 或多或少无关紧要。

"abcde" 是……某处。 "abcde"+1 指向晚一个,并且具有值 "bcde"。无论它指向何处,您都可以将其与空指针(0 是空指针常量)进行比较,并且它不是空指针,因此比较结果为 false。

这是一个格式完美的常量评估,gcc 6.3 碰巧拒绝了它。


虽然我们只是简单地声明 std::less()(p, q) 提供了一些值,在编译时给出了一致的总顺序 并且它在运行时给出了相同的答案。这是……一个有趣的难题。

关于c++ - 为什么 0 == ("abcde"+1) 不是常量表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54424066/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com