what is the output? Please explain, considering i am a novice in c [closed]

匿名 (未验证) 提交于 2019-12-03 02:44:02

问题:

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)); 

回答1:

Time for a crash course on arrays in C.

First of all, let's fix the initializer for the array:

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

This defines a 3-element array of 4-element arrays of int. The type of the expression a is "3-element array of 4-element arrays of int".

Now for the headache-inducing part. Except when it's the operand of the sizeof or unary & operators, or if it's a string literal being used to initialize another array in a declaration, an expression of array type will have its type implicitly converted ("decay") to a pointer type.

If the expression a appears by itself in the code (such as in a statement like printf("%p", a);, its type is converted from "3-element array of 4-element array of int" to "pointer to 4-element array of int", or int (*)[4]. Similarly, if the expression a[i] appears in the code, its type is converted from "4-element array of int" (int [4]) to "pointer to int" (int *). If a or a[i] are operands of either sizeof or &, however, the conversion doesn't happen.

In a similar vein, array subscripting is done through pointer arithmetic: the expression a[i] is interpreted as though it were written *(a+i). You offset i elements from the base of the array and dereference the result. Thus, a[0] is the same as *(a + 0), which is the same as *a. a[i][j] is the same as writing *(*(a + i) + j).

Here's a table summarizing all of the above:

 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 

Hopefully, that should give you everything you need to figure out what the output should be. However, the printf statement should be written as

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


回答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] 

because the 2-dimensional array is initialized as though it had only one dimension.

Complete program, for reference:

#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; } 


回答3:

First of all, your initialization is wrong: your initializer it for one-dimensional array, whereas you declare a two-dimensional one.

Second, let's see what does your code do.

a is a two-dimensional array, so a[0] is of type int[4] (one-dimensional array), and represents the 0-th column of the multidimensional array, and is (mostly) the same as a pointer to the column's leading element. Now you use address arithmetics: a[0] + 1 is the pointer to element after the leading one in the 0-th column (represented as a pointer to it), that is, pointer to the 1-st element in the 0-th column. That's where the second warning appears, saying that your argument to printf is int* and not unsigned int.

Next, *(a[0]+1) dereferences the pointer to the 1-st element of the 0-st column. This is (as usually) equivalent to a[0][1].

Next, *(*(a+0)+1)) is the same, because *(a+0) is the same as a[0].

(In order to understand this all, you need to know some basics: that in C *(x + y) is the same as x[y], and that the 1-dimensional array is essentially the same as the pointer to its leading element.)

About the difference between your book and the reality: the first output value is just a pointer, so it can be an arbitrary value, depending on where your array happened to be in the memory. About the other two values, the question depends on how the array was filled by the wrong initializer.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!