为什么在这种情况下ptr + 1与++ ptr不同?

时间:2018-03-07 01:09:06

标签: c

我原来有以下代码itvoid**

while (it != end)
{
    *it = *(it + 1);
    it++;
}

我决定将it + 1; it++;更改为++it;,因为我计算了两次相同的值。

while (it != end)
{
    *it = *(++it);
}

然而,在这样做之后,我的程序不再以相同的方式运行。

修改我想请注意,这不是i = i++;,而是将it指向的值分配给它前面的值。

2 个答案:

答案 0 :(得分:4)

*it = *(++it);中,编译器可能会为准备引用it而评估*it,然后执行为{{it增加++it的副作用1}}。或者它可能首先执行副作用,然后评估it的{​​{1}}。 C标准没有说明这些必须发生的顺序。在*it中存储值的赋值本身必须更晚,但这是其他的。编译器可以按任何顺序处理左侧部分和右侧部分。

您不允许同时修改对象(*it)并使用它(在++it中),而不确定它们之间的确定顺序。这样做会导致未定义的行为。这是根据C 2011 [N1570] 6.5 2:

  

如果对标量对象的副作用相对于同一标量对象的不同副作用或使用相同标量对象的值进行的值计算未被排序,则行为未定义。

*it中增加it是副作用,在++it中使用it是使用*it的值进行的值计算,这是一个标量对象。因此,行为未定义。

答案 1 :(得分:2)

C99, 6.5表达式

  
      
  1. 在上一个和下一个序列点之间,对象应具有其存储值   通过表达式的评估最多修改一次。此外,先前的值   应只读以确定要存储的值
  2.   

(强调我的。)

*it = *(++it);

我们读了两次并且存储了一次。左侧的*it来自it;右侧的++it读取并存储到it。这里没有序列点。

此表达式具有未定义的行为,因为左侧的读取不用于确定要存储的值。

*it = *(it + 1);是允许的,因为此处未修改it(没有商店),因此您可以拥有任意数量的读取。