【问题标题】:Why is ptr + 1 different from ++ptr in this scenario?在这种情况下,为什么 ptr + 1 与 ++ptr 不同?
【发布时间】:2018-03-07 01:09:05
【问题描述】:

我最初有以下代码,其中it 是void**:

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

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

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

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

编辑:我要注意这不是i = i++;,而是将it指向的值赋给它前面的值。

【问题讨论】:

  • *it = *(++it); 产生未定义的行为,任何事情都可能发生。
  • @HongOoi @Pablo 是吗?这与链接问题中提供的示例不同 i = i++。这是将it 指向的值分配给它前面的值it + 1 或++it。
  • @MichaelSmith 出于同样的原因,它是 UB。 ++it 修改变量it,同时尝试将表达式的结果分配给it。这就是为什么这是未定义的行为,您试图在一个表达式上修改同一个变量两次。赔率是 *it = *(++it); 与 ++it 相同,但谁知道编译器是如何在幕后优化的。按照这个逻辑,第一个代码 sn-p 实际上修改了数组,第二个没有。

标签: c


【解决方案1】:

在*it = *(++it); 中,编译器可能会评估it 以准备引用*it,然后执行为++it 递增it 的副作用。或者它可能会先产生副作用,然后为*it 评估it。 C标准没有说明这些必须以什么顺序发生。赋值本身,在*it 中存储一个值,必须稍后,但那是另一回事。编译器可以按照它想要的任何顺序处理左侧的部分和右侧的部分。

您不能在没有确定顺序的情况下修改对象 (++it) 和使用它 (*it)。这样做会导致未定义的行为。这是根据 C 2011 [N1570] 6.5 2:

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

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

【讨论】:

    【解决方案2】:

    C99,6.5 表达式:

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

    (强调我的。)

    在

    *it = *(++it);
    

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

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

    *it = *(it + 1); 是允许的,因为这里没有修改 it(没有存储),所以你可以有尽可能多的读取。

    【讨论】:

    • C99?您可以找到标准 here 的较新版本的链接。
    猜你喜欢
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    相关资源
    最近更新 更多