开发者

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

This questio开发者_高级运维n is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center. Closed 11 years ago.
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));


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


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜