2014-10-30 20 views
2

我有这行代码:C++ Perincrement不确定的操作对C

front = (++front) % size; 

在C我没有得到任何警告,但在C++中我得到警告operation on front may be undefined [-Wsequence-point]。这种预增量使用如何导致未定义的行为?在我看来,这条线是非常明确的,并且将被解释为:

  1. 增量前
  2. 国防部前与大小
  3. 分配新值前。

是我的编译器只是抛出一个毯子警告?

P.S.我了解警告,如果我正在做类似front = front++;或天堂禁止front = front++ + front++;

编辑:这警告是在码块产生的Windows 64使用GCC(TDM-1)4.6.1

+1

前++ VS ++前不会改变任何东西,左侧等号可以是后置或预先递增的值,这取决于首先评估哪一侧。 AFAIK没有义务在右侧评估=的左侧。 – Borgleader 2014-10-30 18:33:46

+0

我认为thndrwrks的问题取决于这样的想法,即直到'%'和'%'不能发生在'(++ front)'之后才能发生赋值,为了赋予'++'优先级,所以因此没有排序问题。虽然很明显,情况并非如此。我目前对规格不够熟练,无法给出明确的答案,但也许有人可以对此作出说明? – Tommy 2014-10-30 18:37:34

+0

伴侣。发帖前搜索。 – 2014-10-30 18:44:09

回答

3

旧的排序规则有边界情况,其中操作顺序明确定义,但仍然存在技术上未定义的行为。对于C++ 11和C11,通过用'Sequenced-before'和'Sequenced-after'关系替换序列点需求来解决这个问题。

你的例子恰好是这种情况。如果您在C11或C++ 11模式下收到警告,则尚未更新新规则的警告。在早期的C和C++模式下,警告是正确的。如果您在早期模式下没有收到警告,那么他们根本就没有实施,那没关系,因为“不需要诊断”。


与此同时,这条线可以更清楚地写,也可以正确的按照旧规则:

front = (front + 1) % size; 
3

编写递增的值回front可以发生在任何时间(之前或之后的分配修改front) ,所以警告是有效的,代码是不安全的。

+0

C中的这种行为与C++中的行为不同吗? – thndrwrks 2014-10-30 18:44:05

+0

尽我所知,但我对C的知识已过时。 – 2014-10-30 18:57:40

+0

这很有趣 - 我怀疑在传统意义上,代码总是先在右侧进行评估,增量完成后才分配给左侧。但是,也许不是......这不是只有编译器优化应该影响的东西吗? (即没有优化,没有生成的代码得到严格的排序?) – ash 2014-10-30 19:36:47

5

您在序列点之间切换两次:一次为++,一次为赋值。 这是未定义的行为。

4

在C++ 11中,这是明确定义的;结构是相同的:

i = ++i + 1; 

其被给定为在标准本身的良好定义的行为的例子。有关更详细的解释,请参见AndreyT's answer here

在C++ 03,C89和C99中,这是未定义的行为,因为他们对++i有宽松的排序规则。

+0

我不认为这是完全黑白的,因为标准没有明确规定左值到右值转换发生的时间,所以我想围绕讨论围绕这种表达方式将在可预见的将来继续:) – 2014-10-30 19:24:33

+0

我敢打赌,他们将在C++ 11中解决这个问题。让你的程序定义良好或不只是切换编译模式 - 这是非常危险的游戏。 – Slava 2014-10-30 19:26:04

+2

@Slava我们正在谈论C++ 11(和AFAIK它在C++ 14中没有改变)。如果切换到较旧的标准时C++ 11程序中断是“正常”,那么我们应该避免使用另一种方法 – 2014-10-30 19:38:59