首页 文章

逗号运算符是否允许在C 11中使用常量表达式?

提问于
浏览
22

在回答C11的this question on SO的过程中,我意识到在C03(以及C)中,在常量表达式中明确禁止使用逗号运算符 .

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

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

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

例如,以下程序在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)];
}

QUESTION:

关于逗号运算符是否被允许用于常量表达式,或者我是否遗漏了某些内容,C 03和C 11之间是否存在差异?

作为一个奖励(非建设性)问题,我有兴趣知道为什么逗号运算符不能用在C 03中的常量表达式中 .

2 回答

  • 3
    • 是的,我相信这是C 03和C 11之间的变化 . 我相信它是基于你提到的原因而完成的 - 没有特别好的理由逗号运算符不能成为常量表达式的一部分 .

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

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

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

    int x[2, 5];
    

    ...将被拒绝而不是让用户误以为他只有5个元素才真正定义了 x .

  • 14

    但是,必须要说的是,即使是下面的程序也可以使用-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 Baggage 说:

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

    正如您所注意到的,此代码是有效的C 11.但是,顶级逗号在C 11中仍然无效,因为C 11语法中的常量表达式是一种条件表达式(其中顶级逗号是不允许) . 从而:

    int arr[0, 42];
    

    仍然是形象不对 .

相关问题