代码之家  ›  专栏  ›  技术社区  ›  whacko__Cracko

这是一种未定义的行为吗?

  •  4
  • whacko__Cracko  · 技术社区  · 16 年前

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

    *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;
    }
    

    我认为这个表达没有什么好担心的 *p++ = *p + 32;

    5 回复  |  直到 15 年前
        1
  •  8
  •   Loki Astari    16 年前

    首先让我们假设‘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)
    


    编译器可以通过多种方式对这些指令重新排序,
    但需要注意的要点是,(B)可以发生在任何地方,(B)上的唯一约束是它发生在(A)之后,因此(D)中定义的p3值可能是两个不同值之一,具体取决于(B)的确切位置。

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

        2
  •  12
  •   int3    16 年前

    结果 *ptr++ = *ptr + a 没有定义。等号不是序列点,因此使用 ptr 同样,在该语句中,会导致未定义的行为。只要考虑结果 ptr 在计算RHS表达式之前递增,并将其与以下情况进行比较: ptr 是递增的 RHS表达式。

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

    基本上,您只能依靠两件事:在最后一个序列点和下一个序列点之间的某段时间计算后增量,以及表达式 ptr++ ptr 它是递增的。所以 *ptr++ = a 这很好,因为你可以指望 ptr++ .

        3
  •  1
  •   John Bode    16 年前

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

        4
  •  0
  •   asveikau    16 年前

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

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

        5
  •  0
  •   Dani    16 年前

    如果这就是你要问的,那就不一样了。 不过它会编译的。。。

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

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