你能解释一下* ptr ++和*(++ ptr)之间的区别吗?

时间:2012-12-22 00:52:35

标签: c arrays pointers

  

可能重复:
  Pointer Arithmetic: ++*ptr or *ptr++?

我不明白有什么区别?以下是实现* ptr ++

的代码示例
#include <stdio.h>
int my_array[] = {1,23,17,4,-5,100};
int *ptr;
int main(void)
{
int i;
ptr = &my_array[0]; /* point our pointer to the first
element of the array */
printf("\n\n");
for (i = 0; i < 6; i++)
{
printf("my_array[%d] = %d ",i,my_array[i]);
printf("ptr + %d = %d\n",i, *ptr++);

}
return 0;
}

输出

my_array[0] = 1 ptr + 0 = 1
my_array[1] = 23 ptr + 1 = 23
my_array[2] = 17 ptr + 2 = 17
my_array[3] = 4 ptr + 3 = 4
my_array[4] = -5 ptr + 4 = -5
my_array[5] = 100 ptr + 5 = 100

将第二个printf语句更改为printf时(“ptr +%d =%d \ n”,i,*(++ ptr)); 这成为了输出:

my_array[0] = 1 ptr + 0 = 23
my_array[1] = 23 ptr + 1 = 17
my_array[2] = 17 ptr + 2 = 4
my_array[3] = 4 ptr + 3 = -5
my_array[4] = -5 ptr + 4 = 100
my_array[5] = 100 ptr + 5 = -1881141248

有人请详细说明细节差异,以便我理解。

3 个答案:

答案 0 :(得分:3)

一个指针在获取指向的内容之前递增指针,另一个指针在从指针取出后递增。

在第二个示例中,您已经在最后一次迭代中超越了数组的末尾,并且您正在打印(可能)紧跟在数组之后的内存位置(或一些随机垃圾)

答案 1 :(得分:3)

这不可能是一个upvote,因为这个问题无论如何都要关闭,但无论如何我都被迫把它放在这里。

使用*ptr++时会发生以下情况:

  1. 复制ptr
  2. 的现有值
  3. 按类型宽度字节递增ptr(在这种情况下为1,因为char是一个字节)
  4. 从(1)
  5. 中制作的副本中输入先前

    使用*++ptr时会发生以下情况:

    1. 按类型宽度字节递增ptr(在这种情况下为1,因为char是一个字节)
    2. 取消引用ptr的新值。
    3. 对于在临时复制可能非常昂贵的C ++对象上覆盖所述运算符时,后增量的基本复制然后增量要求对于性能至关重要。


      <强>后递增

      以下是对任何怀疑这一点的人的后增量行为:

      #include <stdio.h>
      #include <stdlib.h>
      #include <stdarg.h>
      
      static char test[] = "AB";
      static const char *ptr = test;
      
      void myprintf(const char *fmt, ...)
      {
          va_list args;
          va_start(args, fmt);
          printf("myprintf: %c\n", *ptr);
          vprintf(fmt, args);
      }
      
      int main(int argc, char *argv[])
      {
          myprintf("main: %c\n", *ptr++);
          return EXIT_SUCCESS;
      }
      

      <强>输出

      myprintf: B
      main: A
      

      注意ptr的值在调用main()之前已在myprintf()增加,与大多数人的想法相反,同样与大多数C / C ++教师相反和书籍显然是。对此的反汇编证明了这种情况:

      movq    _ptr(%rip), %rsi     ; ptr value moved into rsi
      movq    %rsi, %rcx           ; ptr value moved into rcx
      addq    $1, %rcx             ; increment value by one
      movq    %rcx, _ptr(%rip)     ; ** store incremented address back into ptr **
      movsbl  (%rsi), %esi         ; old pointer value still in rsi dereferenced here.
      movq    %rax, %rdi           
      movb    $0, %al              
      callq   _myprintf
      movl    $0, %eax
      

      <强>预递增

      上面的相同代码,但使用预增量,意味着将main()中的单个调用更改为:

      myprintf("main: %c\n", *++ptr);
      

      <强>输出

      myprintf: B
      main: B
      

答案 2 :(得分:1)

一个是预增量运算符,另一个是后增量运算符。

printf("%d", i++);与:

相同
printf("%d", i);
i += 1;

虽然printf("%d", ++i);与:

相同
i += 1;
printf("%d", i);