请解释为什么这段代码是正确的或为什么不正确: 在我看来,行++ * 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;
}
答案 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来修改,或者设置为true(如果是) 是bool(这个用法已被弃用)。操作数应是可修改的 左值。操作数的类型应为算术类型或a 指向完全定义的对象类型的指针。价值是新的 操作数的值;这是一个左值。如果x不是bool类型,那么 表达式++ x相当于x + = 1。
醇>