尽管使用指向导航的指针,但数组的地址已更改
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;
}
在这个例子中,我们使用两个指针 ptr1
和 ptr2
并且都指向变量 X
的地址。
内存中的视图类似于:
+----------------+
ptr1 | 0x7ffeeb1c4b48 |
+----------------+
|
|
X v
+----------------+ +---+
ptr2 | 0x7ffeeb1c4b48 |---->| 1 |
+----------------+ +---+
您通过 ptr1
对 X
的值所做的任何更改,当 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
处的值(地址),ptr3
和 ptr4
都指向该值(地址)。因此,在此之后,当您访问 *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)++;
正在更改 tmp
和 argv
指向的地址的值。
这就是为什么当您访问 &(**argv)
的地址时,您得到的值与初始值不同。
此外,在外部 while
循环中,您正在做:
tmp++;
所以,在第一次迭代之后,tmp
和 argv
不再指向同一个地址。
在进一步的迭代中,您将获得 &(**tmp)
的不同值,但 &(**argv)
.
的相同值
希望这对您有所帮助。
我想更好地理解指针运算。我知道如何用索引重写它,但我想了解这里哪里有指针问题。
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;
}
在这个例子中,我们使用两个指针 ptr1
和 ptr2
并且都指向变量 X
的地址。
内存中的视图类似于:
+----------------+
ptr1 | 0x7ffeeb1c4b48 |
+----------------+
|
|
X v
+----------------+ +---+
ptr2 | 0x7ffeeb1c4b48 |---->| 1 |
+----------------+ +---+
您通过 ptr1
对 X
的值所做的任何更改,当 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
处的值(地址),ptr3
和 ptr4
都指向该值(地址)。因此,在此之后,当您访问 *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)++;
正在更改 tmp
和 argv
指向的地址的值。
这就是为什么当您访问 &(**argv)
的地址时,您得到的值与初始值不同。
此外,在外部 while
循环中,您正在做:
tmp++;
所以,在第一次迭代之后,tmp
和 argv
不再指向同一个地址。
在进一步的迭代中,您将获得 &(**tmp)
的不同值,但 &(**argv)
.
希望这对您有所帮助。