int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
printf("%u %u",*(stud+1),stud+1);
printf("%u, %u", &stud,stud);
为什么这个语句打印相似的值,螺柱[1]或*(螺柱+ 1)实际上是一个数组因此必须得到的基地址即&螺柱[0] [0],但螺柱本身是一个指向数组数组的指针。第三条语句也输出相同的值。2D阵列和指针
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
printf("%u %u",*(stud+1),stud+1);
printf("%u, %u", &stud,stud);
为什么这个语句打印相似的值,螺柱[1]或*(螺柱+ 1)实际上是一个数组因此必须得到的基地址即&螺柱[0] [0],但螺柱本身是一个指向数组数组的指针。第三条语句也输出相同的值。2D阵列和指针
在不使用任何衰减语法可能是更清晰的(这些都是作为代码相同的地址;所述第一线是在相反的顺序;以及我的括号是多余的,但希望它提高该实施例的清晰程度):
printf("%p %p\n", &(stud[1]), &(stud[1][0]));
printf("%p %p\n", &(stud), &(stud[0]));
在这两种情况下,行上的第一个地址都与第二个地址匹配,因为数组的第一个元素与数组位于同一地址。数组不能有初始填充,而在C中,对象的地址是其第一个字节的地址。
stud
的第一个元素是stud[0]
,并且stud[1]
的第一个元素是stud[1][0]
。
+1我说的是,但在1/8左右的空间。我真的需要学习何时将其包装= P – WhozCraig
由于您试图显示的所有这些值都是指针,因此应该使用%p
而不是%u
。如果你这样做,你会看到地址指出:
printf("%p, %p", &stud,stud);
是不同于:
printf("%p %p",*(stud+1),stud+1);
,因为如你所说stud
是一个指向数组的数组。
对于表达式都是地址结果,您的观察结果是正确的。但每个标准的那些地址的类型是不同的。你的短语“但是stud本身是一个指向数组数组的指针”。不准确。 stud
是一组数组。指针是而不是阵列。经过几十年的努力想出一个坚实的白话来描述它是如何工作的,并且坚决拒绝走“衰退”板(在C标准中恰好出现一个一个次,甚至在那里它被用作动词-footnote),我能想到的最好的是:
指针不是数组。指针保存了的地址。数组是的地址。
每个表达式如下所示鉴于int stud[5][2];
stud int (*)[2]
stud+1 int (*)[2]
*(stud+1) int *
&stud int (*)[5][2]
记住的是,根据标准中,阵列的表达值是它的第一个元件的地址,和指针到元件型是所述地址的类型。在两个输出中,每对表达式都有相同的地址,但它们是不同的类型。这是可验证与原始代码的一些扩展:
#include <stdio.h>
int main()
{
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
printf("%p %p\n", *(stud+1), stud+1);
printf("%p %p\n", &stud,stud);
int (*p1)[2] = stud+1; // OK
// int (*p2)[2] = *(stud+1); // incompatible types
int *p3 = *(stud+1); // OK
int (*p4)[5][2] = &stud; // OK
return 0;
}
允许分析程序
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
查阅地址将是这样的(假设2字节整数)。括号表示数组中的相应元素。
1 element of 2-D array ---> 4001(1) 4003(2)
2 element of 2-D array ---> 4005(3) 4007(4)
3 element of 2-D array ---> 4009(5) 4011(6)
4 element of 2-D array ---> 4013(7) 4015(8)
5 element of 2-D array ---> 4017(9) 4019(8)
我们知道arr [i]给出数组的第i个元素。所以当我们说stud [0]时,我们期望数组stud[5][2]
的第0个元素。我们可以假设二维数组作为一维数组的集合。所以像printf("%u",stud[0])
这样的声明,我们将显示第0个要打印的元素,以及这个数组的第0个元素是什么。它是一维数组。我们知道,只提一维数组给出了其基地址。因此,printf
将打印第0个一维数组的基地址,依此类推。
有了这些信息,我们可以分析您的问题。
记住螺柱是二维阵列。 stud
被视为指向二维数组的第零个元素的指针。所以(stud + 1)
会给出二维数组的第二个元素的地址。因而打印(stud+1)
会打印柱阵列第二元素的地址。它是什么。从上面的地址将是4005。
现在让我们看看为什么*(stud +1)也给出相同的值。我们知道*(stud +1)
相当于stud[1]
。从上面我们知道stud [1]会打印第二个一维数组的基地址。什么是一维数组在第二个位置是(3,4)的地址是(4005,4007)。那么基地址是什么?它是4005.因此*(stud+1)
也打印4005.
现在你说stud[0] and &stud[0]
打印相同的值。
从上面的stud [0]是一维数组并打印出它的基地址。现在所以& stud [0]应该给出与其基地址相同的1-D数组的地址。因此他们打印相同的地址。
类似的解释将适用于其他情况。
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
上述语句中定义stud
为5
元素,其中每个元素是int[2]
类型,即,2
整数数组的数组。它还使用初始化程序列表初始化数组。
现在,在表达式stud + 1
中,数组stud
衰减为指向其第一个元素的指针。因此,stud + 1
评估为&stud[1]
并且是int (*)[2]
类型,即指向整数的数组的指针。 *(stud + 1)
然后是*(&stud[1])
,即,stud[1]
。 stud[1]
又是一个数组类型,即int[2]
,所以它再次衰减到printf
调用中的第一个元素,即&stud[1][0]
(它是数组stud[1]
的第二元素的基地址)的指针。
请注意stud + 1
和*(stud + 1)
评估到相同的地址,但它们不是相同的类型。
同样,&stud
和stud
衰减到相同的地址,但它们是不同的类型。 stud
的类型为int[5][2]
,其中&stud
的类型为int (*)[5][2]
。
为什么这个语句打印相似的值,螺柱[1]或*(螺柱+ 1)实际上是一个数组因此必须得到的基地址即&螺柱[0] [0],但 螺柱本身是一个指向数组数组的指针。
你错了。 stud[1]
或*(stud + 1)
的基地址是&stud[1][0]
而不是&stud[0][0]
。另外,stud
不是指针,而是数组类型。在某些情况下,它衰减为指向其第一个元素的指针,但这确实意味着它是一个指针。
另外,您应该使用%p
转换说明符来打印地址。
你在问为什么*(stud + 1),stud + 1打印相同的值? –
是的,stud [0]和&stud [0]也打印相同的值。 – bullseye
究竟是什么都不打印子数组的实际内容,以防万一不明显。如果您要打印地址,请使用'%p'作为输出。 – WhozCraig