C++ 这是不是*ptr&x2B+;=*ptr&x2B;a「;未定义的行为?

C++ 这是不是*ptr&x2B+;=*ptr&x2B;a「;未定义的行为?,c++,c,sequence-points,C++,C,Sequence Points,嗯,我并不真的需要这个答案,我只是好奇而已 像*ptr++=a这样的表达式是完全有效的,因为我们在两个对象上操作ptr和*ptr,但是如果我写*ptr++=*ptr+a它仍然有效吗 例如考虑下面的片段: int main(void){ int a[] = {5,7,8,9,2}; int* p =a; *p++ = 76; /*altering the first element */ *p++ = *p + 32; /*altering the second ele

嗯,我并不真的需要这个答案,我只是好奇而已

*ptr++=a
这样的表达式是完全有效的,因为我们在两个对象上操作
ptr
*ptr
,但是如果我写
*ptr++=*ptr+a
它仍然有效吗

例如考虑下面的片段:

int main(void){
   int a[] = {5,7,8,9,2};

   int* p =a;

   *p++ = 76; /*altering the first element */
   *p++ = *p + 32; /*altering the second element */    

   p = a;
   int i;
   for(i = 0;i<5; i++)
      printf("%d ",*p++);

   return 0;
}
int main(无效){
int a[]={5,7,8,9,2};
int*p=a;
*p++=76;/*改变第一个元素*/
*p++=*p+32;/*改变第二个元素*/
p=a;
int i;

对于(i=0;i来说,如果你问的是同一个问题,那么答案就不一样了。 不过它会编译的

这是合法的-如果PTR指向一个数组,而不是该数组的最后一个单元格, 因此,递增的PTR将指向数组中的下一个对象

*ptr++=*ptr+2
与*ptr=*ptr+2相同,ptr++

我认为它没有定义。但是我不确定

但是,更广泛的文体观点是:如果一个表达式让您开始怀疑它是否未定义,那么这可能表明您的代码不清楚其意图,需要减少歧义,并且对求值顺序的不明显依赖性更少


我曾经认为C非常酷,因为你可以写很多非常简短的语句,做很多疯狂的事情。我不再这么想了。:-)<代码> > *PTR++**PTR+A 未定义。等号不是序列点,因此在语句中再次使用“代码> PTR < /代码>的值导致未定义的行为。如果在RHS表达式被评估之前增加代码< PTR ,并将其与<代码> PTR 在RHS表达式之后递增

注意:这并不是说表达式的结果将来自这两个场景中的任何一个。Undefined是Undefined


基本上,您只能依靠两件事:在最后一个序列点和下一个序列点之间的某段时间计算后增量,表达式
ptr++
在其递增之前返回
ptr
的值。因此
*ptr++=a
是可以的,因为您可以依赖
ptr++
的结果

首先让我们假设“p”是指针类型。
否则,所有操作都只是函数调用的语法糖

让我们把这句话分成几部分

int* p = a;

*p++ = *p + 32;

<< Sequence Point >>
// Part 1: p++
// Note the definition of post increment in the standard is (5.2.6)
// The result of the expression p++ is the value of 'p' while the value of the 
// objects represented by 'p' is incremented. This can be represented in pseudo code as:
(A) int*  p1 = p;
(B) p = p + 1;

// Part 2: *p (On the result of Part 1) (On *p++)
(C) int& p2 = *p1;  // Note the use of p1;

// Part 3: *p (On *p + 32)
// Note: There is no linkage between this use of 'p' and the 'p' in Part 1&2
(D) int& p3 = *p;

// Part 4: *p + 32;
(E) int p5 = p3 + 32; // Note the use of p3;

// Part 5: Assignment.
(F) p2 = p5;
<< Sequence Point >>

Ordering that must be preserved:
(A) Before (B)
(A) Before (C)
(D) Before (E)
(C) Before (F)
(E) Before (F)
int*p=a;
*p++=*p+32;
>
//第1部分:p++
//注:标准中的岗位增量定义为(5.2.6)
//表达式p++的结果是'p'的值,而
//“p”表示的对象递增。这可以用伪代码表示为:
(A) int*p1=p;
(B) p=p+1;
//第2部分:*p(基于第1部分的结果)(基于*p++)
(C) int&p2=*p1;//注意p1的用法;
//第三部分:*p(关于*p+32)
//注:第1部分和第2部分中的“p”和“p”之间没有联系
(D) int&p3=*p;
//第4部分:*p+32;
(E) int p5=p3+32;//注意p3的用法;
//第五部分:任务。
(F) p2=p5;
>
必须保留的顺序:
(A) 在(B)之前
(A) 在(C)之前
(D) 在(E)之前
(C) 在(F)之前
(E) 在(F)之前
鉴于上述限制:
编译器可以通过多种方式对这些指令重新排序,
但需要注意的要点是,(B)可以发生在任何地方,(B)上的唯一约束是它发生在(A)之后,因此(D)中定义的p3值可能是两个不同值之一,具体取决于(B)的确切位置

因为p3的值在此无法定义。

结果语句具有未定义的行为。

根据C,
*ptr++=*ptr+32
将根据6.5.2进行未定义:“如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量对象的值计算的值未排序,则该行为未定义。”您正在修改并试图在另一个计算中使用
ptr
的值,而无需插入序列点。

我相信他/她是在问C/C++标准中是否定义了=右侧的*ptr是指向++之前还是之后的字符。
*ptr++=a;
有什么问题吗完全合法。@ysth:嗯,我就是他,我不明白你认为我在问什么;)为什么不*p++=32;?事实上,这对我来说有点奇怪。:-)没有p的声明,这非常重要。@MSalters:有人会认为OP定义“a”是有原因的。还有一个赋值“p=a”。这意味着p是一个int。(否则这个问题就没那么有趣了。)@Debanjan:是的,有很多事情要担心它被定义为向*ptr中添加一个,并使ptr指向下一个元素。唯一的问题是是否存在下一个元素。不。这是因为您不知道
ptr
的值是什么,因为您在当前序列点对之间的其他地方增加了它。
operator=
是函数调用和序列p点(因为它是
操作符*
操作符+
)但它很可能指向内置类型,在这种情况下,解引用、加法和赋值不是运算符,不是函数调用,也不是序列点。实际上..我认为变化不大。函数调用是序列点,但函数参数的求值顺序是任意的。所以他的例子仍然是未定义的。实际上,我认为重载运算符与内置运算符具有完全相同的未定义行为。除了赋值副作用本身(这会发生在
运算符=
内部,因此会受到保护)但是,左侧的
ptr
增量和右侧的
ptr
访问权限仍然是未定义的行为(因为增量的值不是从t