2014-05-24 95 views
1
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阵列和指针

+0

你在问为什么*(stud + 1),stud + 1打印相同的值? –

+0

是的,stud [0]和&stud [0]也打印相同的值。 – bullseye

+0

究竟是什么都不打印子数组的实际内容,以防万一不明显。如果您要打印地址,请使用'%p'作为输出。 – WhozCraig

回答

1

在不使用任何衰减语法可能是更清晰的(这些都是作为代码相同的地址;所述第一线是在相反的顺序;以及我的括号是多余的,但希望它提高该实施例的清晰程度):

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]

+0

+1我说的是,但在1/8左右的空间。我真的需要学习何时将其包装= P – WhozCraig

0

由于您试图显示的所有这些值都是指针,因此应该使用%p而不是%u。如果你这样做,你会看到地址指出:

printf("%p, %p", &stud,stud); 

是不同于:

printf("%p %p",*(stud+1),stud+1); 

,因为如你所说stud是一个指向数组的数组。

2

对于表达式都是地址结果,您的观察结果是正确的。但每个标准的那些地址的类型是不同的。你的短语“但是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; 
} 
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数组的地址。因此他们打印相同的地址。

类似的解释将适用于其他情况。

2
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}}; 

上述语句中定义stud5元素,其中每个元素是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)评估到相同的地址,但它们不是相同的类型。

同样,&studstud衰减到相同的地址,但它们是不同的类型。 stud的类型为int[5][2],其中&stud的类型为int (*)[5][2]

为什么这个语句打印相似的值,螺柱[1]或*(螺柱+ 1)实际上是一个数组因此必须得到的基地址即&螺柱[0] [0],但 螺柱本身是一个指向数组数组的指针。

你错了。 stud[1]*(stud + 1)的基地址是&stud[1][0]而不是&stud[0][0]。另外,stud不是指针,而是数组类型。在某些情况下,它衰减为指向其第一个元素的指针,但这确实意味着它是一个指针。

另外,您应该使用%p转换说明符来打印地址。