我创建了指向指针和int数组的指针,但是当我试图通过指针访问数组时,它跳过一些元素并一次由两个元素移动(例如:从1到3)。这是我的代码:
int main(void) {
int c=10;
int p[5]={2,3,5,6,8};
int *x;
int **y;
x=p;
y=&p;
printf("p value is %d and p points to %d",p,&p);
printf("\n x is %d \n",x[1]);
printf("\n y is %d \n",y[0]);
return 0;
}当我打印y[1]时,它会打印5而不是3,y[2]被打印为8,我想不出原因。有人能帮我吗?指针x运行良好,并沿着x[0]=2、x[1]=3、x[5]=5等正确的元素移动。还有谁能解释一下为什么p和p的值相同?
发布于 2013-08-25 08:57:27
好的,这个问题已经回答了,答案也被接受了,但是即使是被接受的答案也不能解释最初的海报看到的奇怪的结果:为什么y[1]和y[2]打印5和8?这是解释。
发信人:你从以下陈述中得到了什么输出?
printf ("Size of integer: %zu\n", sizeof (int));
printf ("Size of pointer: %zu\n", sizeof (int*));我打赌输出是:
Size of integer: 4
Size of pointer: 8换句话说,我猜您是在64位计算机上编译的,其中整数的大小是4字节,指针的大小是8字节。基于这个假设,下面是正在发生的事情。
p是一个数组。除了少数例外,当在任何表达式中使用时,数组的名称“衰变”到指向其第一个元素的指针。因此,每当您访问p的值时,它都会产生第一个元素的地址。
&p是数组“衰变”到指针规则的例外之一。当应用于数组的名称时,地址运算符返回指向整个数组的指针--而不是指向数组第一个元素的指针。
这意味着p和&p具有相同的值,但它们在语义上非常不同。打印时,您将得到相同的值:
printf("p value is %p and p points to %p", p, &p); // use %p and not %d for addresses但是,这并不意味着p和&p引用的是相同的东西。p是数组的第一个元素的地址,即&p[0]。另一方面,&p是由5个整数组成的整数组的地址。
因此,当您按照以下方式定义x和y时:
int* x = p;
int** y = &p;为x分配一个指向数组第一个元素的指针;为y分配一个指向整个数组的指针。这是一个重要的区别!
此外,声明y的方式与您要分配给它的值之间存在不匹配。&p的类型是int (*) [5];指向5 int数组的指针。y只是指向单个int的指针。您的编译器应该给您一个关于这种不匹配的警告。我的有:
Warning: incompatible pointer types assigning to 'int**' from 'int (*) 5'这种不匹配解释了在打印y[1]和y[2]值时出现的奇怪结果。让我们来看看这些值是怎么回事。
如您所知,数组下标是从数组开始时的抵消:
x[0] == *(x + 0)因此,x[0]产生数组的第一个元素,即2。
x[1] == *(x + 1)但是x是一个指向int的指针。那么,在加法x + 1中到底发生了什么呢?记住指针算术是如何工作的。向指针中添加整数意味着实际上要将整数乘以指向的.元素的大小(在本例中为:
x + 1 == x + (1 * sizeof(int))由于系统上的sizeof(int)是4,所以x[1]的值是数组中的下一个整数,即3。
那么,当您打印y[0]时,这是如何评估的呢?
y[0] == *(y + 0)因此,打印位于y指向的地址的值,即p地址。这是p的第一个元素,因此得到了结果2。
打印y[1]时会发生什么?
y[1] == *(y + 1)但是y是什么呢?这是一个pointer to a pointer to an int。因此,当您将1添加到y时,指针算法的工作方式是再次添加1*指向的元素类型的大小。
y + 1 == y + (1 * sizeof (int*))int*的大小是8个字节,而不是4个字节!因此,每次增量y 1时,都会增加8个字节,即两个整数的大小。因此,当您取消对该值的引用时,您将得到的不是数组中的下一个整数,而是距数组2的整数。
为了更清楚地解释:让我们假设数组从元素1000开始。然后,由于每个int需要4个字节,因此如下所示:
Address Element
-----------------------
1000 2
1004 3
1008 5
1012 6
1016 8
p == &p == x == y == 1000
*x == *y == 2当你把1加到x的时候,你就是在添加1* sizeof(int),也就是说,你实际上是在添加4,所以你得到了1004,而*(x + 1),或者x[1],给了你3。
但是当你把1加到y的时候,你就是在添加1* sizeof(int*),也就是说,你实际上是在添加8,所以你得到了1008,而*(y + 1)给出了地址1008或5的元素。
这解释了您正在获得的输出。然而,这并不是一种合理的编码方式。您不应该期望指针的大小总是8字节。不应将int (*) []分配给int**。您不应该取消指向指向int的指针的引用,并期望得到int结果。总是注意编译器警告。
发布于 2013-08-25 07:07:28
这至少提供了一个清晰的编译,并使用%p打印指针:
#include <stdio.h>
int main(void)
{
int p[5]={2,3,5,6,8};
int *x = p;
int **y = &x;
printf("p value is %p and the address of p is %p and p points to %d\n", (void *)p, (void *)&p, *p);
printf("x[1] is %d\n", x[1]);
printf("y[0] is the address %p\n", (void *)y[0]);
printf("y[0][0] is %d\n", y[0][0]);
return 0;
}示例输出(Mac 10.8.4,GCC 4.8.1,64位编译):
p value is 0x7fff5a1a54d0 and the address of p is 0x7fff5a1a54d0 and p points to 2
x[1] is 3
y[0] is the address 0x7fff5a1a54d0
y[0][0] is 2发布于 2013-08-25 07:27:41
记住,数组名称在大多数表达式中很容易变成指向第一个元素的指针。内存中的p[]数组类似于(地址是假设的):
p
200 204 208 212 216
+----+----+----+----+---+
| 2 | 3 | 5 | 6 | 8 |
+----+----+----+----+---+
▲ ▲ ▲ ▲ ▲
| | | | |
p p+1 p+2 p+3 p+3在x = p;之后,x也指向第一个元素。
p
200 204 208 212 216
+----+----+----+----+---+
| 2 | 3 | 5 | 6 | 8 |
+----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲
| | | | | |
| p p+1 p+2 p+3 p+3
|
x
+----+
| 200|
+----+在表达式y = &p;中,&p是int(*)[5]类型数组的指针,y是int**。(您必须得到用-Wall编译的警告(或错误))。
读:p
因为p和&p在价值上是相同的,所以y的地址值也与p相同。
p
200 204 208 212 216
+----+----+----+----+---+
| 2 | 3 | 5 | 6 | 8 |
+----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲
| | | | | |
| p p+1 p+2 p+3 p+3
|
x y
+----+ +----+
| 200| | 200|
+----+ +----+
int* int**你的第一张照片:
printf("p value is %d and p points to %d",p,&p);应写为:
printf("p value is %p and p points to %p", (void*)p, (void*)&p);
// ^ ^ 使用%p而不是%d,因为您正在打印地址,而且void*的类型也是必要的,因为%p需要void*。正如我所说,按价值计算,p和&p是相同的,两个地址都是相同的。
第二印件f:
printf("\n x is %d \n", x[1]);输出:3 as x指向数组x[1] == *(x + 1) == 3中的第一个元素(在我的图x + 1 == 204中)。
第三印件f:
printf("\n y is %d \n", y[0]);注y类型为int**,因此y[0] == *(y + 0) = *y值存储在y类型*y is int*中。
因此,由于y[0]是int*,所以您应该使用%p而不是%d。
但是上面的printf语句打印第一个元素的值,即:2。
类似地,y[1]打印3,y[2]打印5。
编辑
当我打印
y[1]时,它将打印5而不是3,y[2]被打印为8。
不,正如我前面解释过的那样,它输出@码页,其中sizeof(int) == sizeof(int*)可能在您的系统中sizeof(int*) = sizeof(int)的两倍(64位编译器),所以当您在下一个位置旁边添加一个地址时。
正如@WhozCraig评论的:试试y = &x;,你可能会有更好的运气。并打印您要传递的任何内容,应该是%p的“指针”。
更正你的代码。
https://stackoverflow.com/questions/18426474
复制相似问题