这是不确定的行为,为什么?

时间:2012-01-13 09:29:28

标签: c++

请解释为什么这段代码是正确的或为什么不正确: 在我看来,行++ * p1 = * p2 ++有未定义的行为,因为p1首先被解除引用然后递增。

int main()
{
   char a[] = "Hello";
   char b[] = "World";

   char* p1 = a;
   char* p2 = b;

   //*++p1 = *p2++; // is this OK?
   ++*p1 = *p2++; // is this OK? Or this is UB?

   std::cout << a << "\n" << b;

   return 0;
}

2 个答案:

答案 0 :(得分:9)

第一个没问题

*++p1 = *p2++ // p1++; *p1 = *p2; p2++;

第二个是带有C ++的UB,因为你要修改p1指向的内容两次(一次是因为增量而一次是因为赋值),并且没有序列点将两个副作用分开。

使用C ++ 0x规则,解释和理解的东西是不同的,也是更复杂的。如果你像第二个那样写故意表达,如果它不适合代码高尔夫比赛,如果你为我工作,那么认为自己被解雇了(即使这在C ++ 0x中是合法的)。

我不知道它在C ++ 0x中是否合法,我不想知道。我太少的神经元会以这种方式浪费它们。

答案 1 :(得分:1)

未定义的行为。即使实现已定义未指定也不存在。 (这三个术语都是不同的东西。)

这两行都很明确,但它们做了不同的事情。

*++p1 = *p2++;

相当于

_T1* _p1 = ++p1;
T2_* p2_ = p2++;
*_p1 = *p2_;

++*p1 = *p2++;

相当于

T1& x = *p1;
__T1_& y = ++x;
T2_* p2_ = p2++;
y = *p2_;

其中

  • T1&*p1表达式的类型,
  • _T1*++p1表达式的类型,
  • T2_*p2++表达式的类型,
  • __T1_&++(*p1)表达式的类型,

    即。在您的情况下,所有T1/_T1/__T1_/T2_都是char

由于++x(对于C ++本机类型)在您的案例x中返回对x的引用,而y是相同的引用(即*p1) - 但如果T1是一些重载operator++()的自定义类型,则情况可能并非如此。

添加

显然增加值然后分配给它是完全没有意义的。

是的 - 就像其他人已经说过的那样,只是不写你有这些问题的代码。写下你清楚的内容并且应该向读者清楚。

<强> ADD2:

为了澄清有争议的观点,我将引用标准。

ISO / IEC 14882-2003 5.3.2:

  
      
  1. 前缀++的操作数通过添加1来修改,或者设置为true(如果是)   是bool(这个用法已被弃用)。操作数应是可修改的   左值。操作数的类型应为算术类型或a   指向完全定义的对象类型的指针。价值是新的   操作数的值;这是一个左值。如果x不是bool类型,那么   表达式++ x相当于x + = 1。
  2.