尽管使用指向导航的指针,但数组的地址已更改

Address of an array changed despite using a pointer to navigation

我想更好地理解指针运算。我知道如何用索引重写它,但我想了解这里哪里有指针问题。

int     main(int argc, char **argv)
{
    int i;
    char **tmp;

    i=1;
    argv++;
    tmp = argv; // address of first element of array is:  e2b9f187
    printf("ptr: %x **ptr: %x\n", argv, &(**argv));
    printf("tmp: %x **tmp: %x\n", tmp, &(**tmp));
    while (--argc)
    {
        while(**tmp)
            (*tmp)++;
        printf("step %x ptr %x **ptr %x\n", i, argv, &(**argv));
        printf("step %x tmp %x **tmp %x\n", i, tmp, &(**tmp));
        i++;
        tmp++;
    } 
}

/* 在第一次迭代中,两个地址都发生了变化:**tmp: e2b9f18b**argv: e2b9f18b,在下一次迭代中,仅更改了 *tmp 个位置。 我的问题是为什么尽管使用了指针,**argv 的地址却发生了变化。 提前致谢。

My question is why despite using a pointer, the address of **argv changes.

要理解这一点,首先需要理解双指针(pointer to pointer)的概念。

让我们考虑一个例子:

#include <stdio.h>

int main()
{   
    int X = 1; 
    int *ptr1, *ptr2;

    ptr1 = &X;
    ptr2 = ptr1;

    printf ("ptr1 : %p, ptr2 : %p\n", ptr1, ptr2);
    printf ("*ptr1 : %d, *ptr2 : %d\n", *ptr1, *ptr2);

    (*ptr1)++;
    printf ("ptr1 : %p, ptr2 : %p\n", ptr1, ptr2);
    printf ("*ptr1 : %d, *ptr2 : %d\n", *ptr1, *ptr2);

    return 0;
}

在这个例子中,我们使用两个指针 ptr1ptr2 并且都指向变量 X 的地址。 内存中的视图类似于:

                 +----------------+
            ptr1 | 0x7ffeeb1c4b48 |
                 +----------------+
                              |
                              |
                            X v
     +----------------+     +---+
ptr2 | 0x7ffeeb1c4b48 |---->| 1 |
     +----------------+     +---+

您通过 ptr1X 的值所做的任何更改,当 X 的内存位置的值将通过 [= 访问时,更改的值将反映出来20=] 反之亦然。

The output of program is:
ptr1 : 0x7ffeeb1c4b48, ptr2 : 0x7ffeeb1c4b48
*ptr1 : 1, *ptr2 : 1
ptr1 : 0x7ffeeb1c4b48, ptr2 : 0x7ffeeb1c4b48
*ptr1 : 2, *ptr2 : 2

现在,我们修改程序,引入双指针:

#include <stdio.h>
int main()
{
    int X = 1;
    int *ptr1;

    ptr1 = &X;
    printf ("ptr1 : %p\n", ptr1);

    int **ptr3, **ptr4;

    ptr3 = &ptr1;
    ptr4 = ptr3;

    printf ("ptr3 : %p, ptr4 : %p\n", ptr3, ptr4);
    printf ("*ptr3 : %p, *ptr4 : %p\n", *ptr3, *ptr4);
    printf ("**ptr3 : %d, **ptr4 : %d\n", **ptr3, **ptr4);

    (*ptr3)++;
    printf ("ptr1 : %p, *ptr1: %d\n", ptr1, *ptr1);
    printf ("ptr3 : %p, ptr4 : %p\n", ptr3, ptr4);
    printf ("*ptr3 : %p, *ptr4 : %p\n", *ptr3, *ptr4);
    printf ("**ptr3 : %d, **ptr4 : %d\n", **ptr3, **ptr4);

    return 0;
}

在程序中,语句:

(*ptr3)++;

将更改 ptr1 处的值(地址),ptr3ptr4 都指向该值(地址)。因此,在此之后,当您访问 *ptr4**ptr4 时,更改的值将被反映出来,类似于第一个示例中的单指针 ptr2

内存中的视图现在将类似于:

                           ptr1                       X
     +---------------+      +----------------+      +---+
ptr3 | 0x7ffeebc3fb40|----->| 0x7ffeebc3fb48 |----->| 1 |
     +---------------+      +----------------+      +---+
                                ^
                                |
                    +----------------+
               ptr4 | 0x7ffeebc3fb40 |
                    +----------------+

程序输出为:

ptr1 : 0x7ffeeab5db48
ptr3 : 0x7ffeeab5db40, ptr4 : 0x7ffeeab5db40
*ptr3 : 0x7ffeeab5db48, *ptr4 : 0x7ffeeab5db48
**ptr3 : 1, **ptr4 : 1
ptr1 : 0x7ffeeab5db4c, *ptr1: 0      <=============== ptr1 now pointing to different mem location
ptr3 : 0x7ffeeab5db40, ptr4 : 0x7ffeeab5db40
*ptr3 : 0x7ffeeab5db4c, *ptr4 : 0x7ffeeab5db4c
**ptr3 : 0, **ptr4 : 0

在这里,您可以看到ptr1指向的地址已因(*ptr3)++而更改。

这就是您的程序中发生的情况。在你的程序中,你正在做:

        while(**tmp)
        (*tmp)++;

正在更改 tmpargv 指向的地址的值。 这就是为什么当您访问 &(**argv) 的地址时,您得到的值与初始值不同。

此外,在外部 while 循环中,您正在做:

tmp++;

所以,在第一次迭代之后,tmpargv 不再指向同一个地址。 在进一步的迭代中,您将获得 &(**tmp) 的不同值,但 &(**argv).

的相同值

希望这对您有所帮助。