-3

可能重复:
指针算术:++*ptr 或 *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

有人请详细解释差异,以便我理解。

4

3 回答 3

3

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

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

于 2012-12-22T00:55:42.450 回答
3

这没有投票的机会,因为无论如何这个问题都将被关闭,但无论如何我还是不得不把它放在这里。

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

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

使用*++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已经增加,这与大多数人的想法相反,也与大多数 C/C++ 讲师和书籍显然的相反。对此的反汇编证明了这种情况:main()myprintf()

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
于 2012-12-22T02:13:37.577 回答
1

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

printf("%d", i++);是相同的:

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

虽然printf("%d", ++i);与以下内容相同:

i += 1;
printf("%d", i);
于 2012-12-22T00:59:39.613 回答