C ++ 14和C ++ 17之间的区别在于:`* p ++ = * p`

App*_*son 36 c++ c++14 c++17

在编写一些代码时,我遇到了一个问题,即我设置的值设置错误。我最终找到了罪魁祸首,并在测试时发现它在C ++ 14和C ++ 17上的表现有所不同。代码如下:

#include <stdio.h>
#include <cstdint>
#include <cstring>

int main()
{
    uint8_t *p = new uint8_t[3];
    memset(p, 0x00, 1);
    p++;
    memset(p, 0xF0, 1);
    p++;
    memset(p, 0xFF, 1);
    p--;
    p--;

    // This line in particular
    *p++ = *p;

    *p++ = 0x0F;

    p--;
    p--;

    printf("Position 0 has value %u\n", *p);
    p++;
    printf("Position 1 has value %u\n", *p);
    p++;
    printf("Position 2 has value %u\n", *p);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在C ++ 14上它打印:

Position 0 has value 240
Position 1 has value 15
Position 2 has value 255
Run Code Online (Sandbox Code Playgroud)

并在C ++ 17上打印:

Position 0 has value 0
Position 1 has value 15
Position 2 has value 255
Run Code Online (Sandbox Code Playgroud)

我很好奇为什么它在不同的C ++版本上表现不同。看起来在C ++ 14 *p上,赋值的右侧是在后面评估的++。这个改变了吗?如果++优先级高,为什么在赋值运算符左侧取消引用之前就不会发生呢?

Lig*_*ica 56

读取和写入变量(通过后增量)曾经具有不确定的行为,因为变量=没有引入序列点。您可能在C ++ 14中收到了任何行为(或没有任何行为,或发生了爆炸)。

现在,为这种情况定义了一个排序顺序,您的C ++ 17结果是可靠的。

尽管它仍然很糟糕,但是不应该编写不清楚的代码!

  • @Kaz实际上,右优先评估是直观的。考虑`CreateObject()= MayThrow()`-如果RHS抛出,您是否期望创建一个对象?不! (2认同)
  • 请注意,链接中的示例与原始代码不同(尽管应用相同的标准引号),在“i = i++”(C++17 之前)中,增量与赋值不排序,但在“*p++ = *”中p` 增量未按正确的操作数值计算排序 (2认同)