2011-08-01 16 views
-4
int a[3][4] = { 
      1,2,3,4, 
      5,6,7,8, 
      9,10,11,12, 
      }; 
printf("%u %u %u \n", a[0]+1, *(a[0]+1), *(*(a+0)+1)); 
+2

这个问题听起来很可疑。你为什么需要这个? – hugomg

+7

运行它并找出。 – Eddie

+5

http://ideone.com/vD9It – eckes

回答

12

时间为C.在阵列上速成班

首先,让我们来修复初始化为数组:

int a[3][4] = { 
       { 1, 2, 3, 4}, 
       { 5, 6, 7, 8}, 
       { 9, 10, 11, 12} 
       }; 

这定义的4-元件阵列的一个3元素数组int表达式的类型a是“int的4元素阵列的3元阵列”。

现在为头痛诱导部分。除了它是sizeof或一元&运算符的操作数,或者它是一个用于在声明中初始化另一个数组的字符串文本,数组类型的表达式将其类型隐式转换(“decay”)为指针类型。

如果表达式a本身出现在代码(例如在像printf("%p", a);声明,其类型是从“3元素数组4元件的阵列的int”到“指针4个元素的数组转换int“或int (*)[4]。类似地,如果表达式a[i]出现在代码中,则其类型从“int”(int [4])的“4元件阵列”转换为“指向int”(int *)的指针。如果aa[i]sizeof&的操作数,则转换不会发生。

以类似的方式,数组下标是通过指针算术完成的:表达式a[i]被解释为它被编写为*(a+i)。您从数组的底部偏移i元素并取消引用结果。因此,a[0]*(a + 0)相同,与*a相同。 a[i][j]与编写*(*(a + i) + j)相同。

这里有一个表,列出上述所有的:

 
Expression Type   Decays To Resulting Value 
---------- ----   --------- ----- 
     a int [3][4] int (*)[4] Address of the first element of the array 
     &a int (*)[3][4] n/a   Same as above, but type is different 
     *a int [4]  int *  Same as above, but type is different 
     a[0] int [4]  int *  Same as above 
    *(a+0) int [4]  int *  Same as above 
     a[i] int [4]  int *  Address of the first element of the i'th subarray 
    *(a+i) int [4]  int *  Same as above 
    &a[i] int (*)[4] n/a   Same as above, but type is different 
    *a[i] int   n/a   Value of the 0'th element of the i'th subarray 
    a[i][j] int      Value of the j'th element of the i'th subarray 
*(a[i]+j) int      Same as above 
*(*(a+i)+j) int      Same as above 

希望,这应该给你你需要弄清楚的输出应该是什么样的一切。然而,printf声明应写为

printf("%p %d %d\n", (void *) a[0]+1, *(a[0]+1), *(*(a+0)+1)); 
+0

@ john博德:是的,我知道了,谢谢你的时间。 :) –

+0

哇,非常好的答案。 –

2
$ gcc -Wall -o output output.c 
output.c: In function ‘main’: 
output.c:5:5: warning: missing braces around initializer [-Wmissing-braces] 
output.c:5:5: warning: (near initialization for ‘a[0]’) [-Wmissing-braces] 
output.c:9:5: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat] 

因为虽然它只有一维二维数组初始化。

完整的程序,以供参考:

所有的
#include <stdio.h> 

int main() 
{ 
    int a[3][4] = {1,2,3,4, 
        5,6,7,8, 
        9,10,11,12, 
    }; 
    printf ("%u %u %u \n", a[0]+1, *(a[0]+1), *(*(a+0)+1)); 
    return 0; 
} 
0

首先,你的初始化是错误的:你初始化它的一维数组,而你声明一个二维的一个。

其次,让我们看看你的代码是做什么的。

a是一个二维阵列,所以a[0]int[4]型(一维阵列),以及表示多维阵列的第0列,并且是(大部分)相同的指针列的主导元素。现在使用地址算术:a[0] + 1是指向第0列中的前导元素(表示为指向它的指针)之后的元素的指针,即指向第0列中第1个元素的指针。这就是第二个警告出现的地方,说你的论点是printfint*而不是unsigned int

接下来,*(a[0]+1)取消引用指向第0列的第1个元素的指针。这是(通常)相当于a[0][1]

接下来,*(*(a+0)+1))是一样的,因为*(a+0)a[0]相同。

(一切为了理解这一点,你需要了解一些基本知识:在C *(x + y)是一样的x[y],而一维数组本质上是一样的指针,其主导因素。)

关于你的书和现实之间的区别:第一个输出值只是一个指针,所以它可以是一个任意值,这取决于你的数组在内存中的位置。关于其他两个值,问题取决于数组是如何由错误的初始化程序填充的。

+0

我同意一个人可能不应该初始化这样的事情,但从强烈的意义上说它不是“错误的”。该标准明确允许这样的“平坦”初始化。 –

相关问题