我在这里有一段代码,我有点困惑。似乎如果我使用:p = &j
,只需要两个增量就可以开始遍历a[]
:
#include <stdio.h>
int main(void) {
int a[4] = {5,2,6,4};
int j = a[0];
int *p;
p = &j;
printf("*p = %d\n", *p);
printf("a[0] = %d\n", a[0]);
printf("address of a[0] = %p\n", &a[0]);
printf("\np++\n\n");
p++;
printf("*p = %d\n", *p);
printf("a[1] = %d\n", a[1]);
printf("address of a[1] = %p\n", &a[1]);
printf("\np++\n\n");
p++;
printf("*p = %d\n", *p);
printf("a[2] = %d\n", a[2]);
printf("address of a[2] = %p\n", &a[2]);
return 0;
}
如果我使用p = &a[0]
,那么它可以正常工作。为什么当我使用&j
时,需要两个p++
才能启动。在开始递增数组之前,您可以看到*p = 5
两次。为什么是这样?任何帮助将不胜感激。
答案 0 :(得分:2)
这是一个非常酷的错误,特别是对于刚开始学习C的人来说。理解这种看似奇怪的行为将会提高您对程序运作方式的理解。
您的代码无法正常运行,因为int j
和a[0]
的地址不同,即&j != &a[0]
。
让我用图解来解释原因。
您的所有本地变量a[], j, p, etc...
都会在您的计划call stack上分配。
因此,在您的示例中,堆栈可能假设看起来像这样:
您可以在此精彩艺术图表中看到a
的地址为0x1004
,而j
的地址评估为0x1000
。< / p>
仅仅因为2个变量具有相同的值并不意味着它们具有相同的内存地址。这就是这里发生的事情。你给j一个[0]的值,但它们仍然是2个单独的,不相关的内存。
为什么递增指针的神秘行为会让您处于a[]
的开头可以解释为j
和a[]
都分配在堆栈< / strong>即可。 j的地址可能会在a[]
的地址下方。事实上,正如你在我的巨着艺术中所看到的那样,如果我们从&j
向上移动4个字节,我们就会到达&a[]
。
根据Eugene Sh。编辑1:
请注意:递增这样的指针是C程序中未定义的行为。堆栈上的变量排序是未定义的,并且取决于编译器,每次代码重新编译时,您可能会得到不同的结果。请永远不要在真正的计划中做过这件事。执行p ++会导致未定义的行为。
编辑2:
您可以通过打印所有变量的地址来执行很酷的实验。
int main()
{
int a[4] = {5, 2, 6, 4};
int j = a[0];
int* p;
//in printf, %p stands for "print pointer"
printf("&a[0] = %p\n", &a[0]);
printf("&j = %p\n", &j);
printf("&p = %p\n", &p); //the address of a pointer.... craaazy
printf("p = %p\n", p); //should print same address as &j
//..............................
}
答案 1 :(得分:1)
您在此处遇到未定义的行为。将j
的地址转换为p
,您只能获得j
的地址,而不是a
的开头。第int j = a[0];
行将第一个a
s元素的值分配给j
,但不是其地址。通过递增p
,您将超出已定义的内存空间的边界,从而调用UB。
答案 2 :(得分:1)
你必须记住如何使指针指向数组的一部分。你正在做的是将值赋给整数的地址(指向所述数组的元素0 ......麻烦)。
以下是一个例子:
#include <stdio.h>
int main(void)
{
int a[4] = {5,2,6,4};
/* Always initialize your variables */
int *p = NULL;
int i = 0;
p = a;
for (i=0; i < 4; i++)
{
printf("Number is = %d,\n", p[i]); // or p + i * sizeof(int)
}
return 0;
}
---Results are----
./a.out
Number is = 5,
Number is = 2,
Number is = 6,
Number is = 4,
答案 3 :(得分:0)
int j = a[0]
不使j成为数组a的第一个元素的别名,它定义了一个新的int变量j,它初始化为a的第一个元素的副本。 因此
p = &j;
p不指向a的任何元素,而是指向单独的变量j。
答案 4 :(得分:0)
由于我无法添加评论,这是我对以前的答案做出反应的唯一方法,我自己也会这样做。