其他分享
首页 > 其他分享> > c-为什么这种不确定的行为?

c-为什么这种不确定的行为?

作者:互联网

这是示例代码:

X * makeX(int index) { return new X(index); }
struct Tmp {
    mutable int count;
    Tmp() : count(0) {}
    const X ** getX() const { 
        static const X* x[] = { makeX(count++), makeX(count++) };
        return x; 
    }
};

这将报告静态数组构造中CLang版本500的未定义行为.
为了简化本文,计数不是静态的,但不会改变任何内容.我收到的错误如下:

test.cpp:8:44: warning: multiple unsequenced modifications to ‘count’ [-Wunsequenced]

解决方法:

更新2

因此,经过一些研究,尽管评估顺序未指定,但我实际上定义得很好.将各个部分放在一起是非常有趣的,尽管对于the C++11 case有一个更笼统的问题,但对于C 11之前的案例并没有一个笼统的问题,因此我最终创建了一个涵盖所有细节的自助回答Are multiple mutations of the same variable within initializer lists undefined behavior pre C++11.

基本上,当看到makeX(count)和makeX(count)时,本能是将整个事物视为完整表达式,但并非如此,因此每个初始化器都有一个序列点.

更新

正如James指出的那样,C 11之前的版本可能不是未定义的,它似乎依赖于将每个元素的初始化解释为完整的表达式,但是尚不清楚您是否可以肯定地声明.

原版的

在C 11之前的版本中,在一个序列点中多次修改变量是undefined behavior,我们可以看到,通过查看older draft standard中的相关部分,可以看到第5部分Expressions第4段说(强调我的意思):

[…]Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.

在C 11 draft standard中进行了更改,并从1.9节的以下措辞更改为:程序执行第15段(强调我的意思):

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. […] If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

我们可以从第8.5.4节“列表初始化”第4段看到,对于初始化列表来说:

Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.

标签:c,undefined-behavior,clang
来源: https://codeday.me/bug/20191012/1899733.html