【问题标题】:Can you explain the difference between *ptr++ and *(++ptr)? [duplicate]你能解释一下 *ptr++ 和 *(++ptr) 之间的区别吗? [复制]
【发布时间】:2012-12-09 13:26:44
【问题描述】:

可能重复:
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

请哪位大神详细解释一下区别,以便我理解。

【问题讨论】:

  • *++ptr 递增,然后返回 当前 eval,*ptr++ 递增,然后返回 prior eval。这在许多questionsanswers 中都有涉及,仅举几例。

标签: c arrays pointers


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    这没有任何投票的机会,因为无论如何这个问题即将结束,但无论如何我还是不得不把它放在这里。

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

    1. 复制ptr 的现有值
    2. ptr 增加类型宽度字节(在本例中为一,因为char 为一字节)
    3. 从 (1) 中制作的副本中删除 prior

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

    1. ptr 增加类型宽度字节(在本例中为一,因为char 为一字节)
    2. 取消引用 ptr 的新值。

    在临时复制可能非常昂贵的 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 的值在myprintf() 调用之前已经在main() 中增加了,这与大多数人的想法相反,同样也与大多数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
    

    【讨论】:

      【解决方案3】:

      一个是前自增运算符,另一个是后自增运算符。

      printf("%d", i++); 等同于:

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

      printf("%d", ++i); 等同于:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-04
        • 2016-05-20
        • 1970-01-01
        • 2013-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多