C ++ 11中的常量表达式中是不是允许逗号运算符?

Posted

技术标签:

【中文标题】C ++ 11中的常量表达式中是不是允许逗号运算符?【英文标题】:Is the comma operator allowed in a constant-expression in C++11?C ++ 11中的常量表达式中是否允许逗号运算符? 【发布时间】:2013-05-10 17:26:06 【问题描述】:

在为 C++11 回答 this question on SO 的过程中,我意识到在 C++03(以及 C)中,在 constant-expression。

C++03 标准关于常量表达式的第 5.19/1 段说:

[...] 特别是,除了 sizeof 表达式、函数、类对象、指针或 不应使用引用,并且应使用赋值、递增、递减、函数调用或 逗号运算符 不能使用

然而,在 C++11 中,最后提到逗号运算符的部分似乎消失了。虽然 C++11 标准的第 5.19/2 段明确规定赋值、递增、递减和非constexpr 函数调用表达式不得作为 constant-expression 的子表达式出现, 逗号运算符的使用似乎不再被禁止了。

例如,以下程序在 GCC 4.7.2 和 Clang 3.3 上使用 std=c++11 编译良好(除了编译器警告说逗号运算符无效并且 xarr 变量未使用):

int main()

    constexpr int x = (0, 42);
    int arr[(0, 42)];

但是,必须说即使下面的程序使用 -std=c++03 选项(在 Clang 和 GCC 上)也可以正常编译,这显然是正确的,因为上面引用了 C ++03 标准:

int main()

    int arr[(0, 42)];

问题:

C++03 和 C++11 在常量表达式中是否允许使用逗号操作符有区别,还是我遗漏了什么?

作为一个奖励(非建设性)问题,我很想知道为什么逗号运算符不能用于 C++03 中的常量表达式。

【问题讨论】:

【参考方案1】:

    是的,我相信这是 C++03 和 C++11 之间的变化。我相信这样做的大致原因是您提到的 - 没有特别好的理由逗号运算符不能成为常量表达式的一部分。

    我相信 C++03 中的规则源自 C 中的规则(C90,§6.4):

常量表达式不应包含赋值、递增、递减、函数调用或逗号运算符,除非它们包含在 sizeof 运算符的操作数中。

至于为什么C语言的常量表达式中禁止使用逗号,我只能推测。我的直接猜测是确保如下定义:

int x[5, 2];

...将被拒绝。如果它被允许,它可能会导致程序员错误地认为他定义了一个 5x2 元素数组(总共 10 个元素),而(如果在那里允许逗号运算符)他真的定义了 x只有 2 个元素(5 被完全忽略)。

至于为什么 C++ 委员会认为这是一个比 C 委员会更容易接受的风险,我想这归结为一个相当简单的情况:C 几乎没有提供替代方案,因此使用了相当多的数组。另一方面,C++ 同时提供了std::arraystd::vector,在极少数情况下有很多理由使用“原始”数组,因此问题出现的可能性要小得多。

【讨论】:

【参考方案2】:

但是,必须说即使以下程序也可以使用 -std=c++03 选项(在 Clang 和 GCC 上)编译良好,鉴于上述 C++03 的引用,这显然是不正确的标准

没那么快。您还需要使用-pedantic(或-pedantic-errors)让Clang 和GCC 严格执行C++03 规则。有了这个,GCC 主干说:

<stdin>:1:16: error: array bound is not an integer constant before ‘]’ token

Clang 树干说:

<stdin>:1:19: error: variable length arrays are a C99 feature [-Werror,-Wvla-extension]
void f()  int arr[(0, 42)]; 
                  ^

如您所见,此代码是有效的 C++11。但是,top-level 逗号在 C++11 中仍然无效,因为 C++11 语法中的 constant-expression 是一种 conditional -expression(不允许使用***逗号)。因此:

int arr[0, 42];

仍然不正确。

【讨论】:

以上是关于C ++ 11中的常量表达式中是不是允许逗号运算符?的主要内容,如果未能解决你的问题,请参考以下文章

C语言中逗号表达式的实用意义或者产生的原因?

c ++中的逗号运算符不计算第二个表达式

“算术表达式”是不是允许在 C 中用逗号分隔,或者我们需要为每个单独的语句?

C语言表达式和语句

databinding对应啥格式的数据源

作业七 总结